1

ネストされたループで反復ごとに1回だけ何かを行う最も賢い方法は何ですか?外側のループが非常に複雑なため、不変部分を引き出すことができません。これが私のC++の例です:

void foo::bar() {
    if(oldCycle == tree.cycle) {
        doSomething();
        oldCycle++;
    }
}

このメソッドは、tree.cycleがインクリメントされるまで頻繁に呼び出されます。oldCycleはfooのプライベートメンバー変数です

claas foo {
public: ...

private:
int oldCycle;
};

コンパイラはこのコードを最適化しますか、それともifチェックは反復ごとに実行されますか?

編集:ここでは、ループを使用してコードを要求したように、最初のループはmexFunction()メソッドにあり、アルゴリズムはmatlabで開始され、mexFunctionを呼び出します。

void mexFunction(...) {
    for( tree.cycle = 0; tree.cycle<maxIt; tree.cycle++ ) {
        foo->startfoo();
    }
}

そしてここに他のループがあります:

void foo::startfoo() {
    for(tree.cur_it = 0; tree.cur_it <=39; tree.cur_it++ ) {
        bar();
    }
}
4

2 に答える 2

3

一般的な条件では、コレクションから特別なケースを何らかの方法で削除する必要があるため、これを実際に最適化することはできません。

ただし、最初の要素を特別に処理する特殊なケース(たとえば、区切り文字を使用して範囲を印刷する場合"1, 2, 3")には、Knuthの「ループアンドハーフ」を使用できます。

ナイーブループ:

for (unsigned int i = 0; i != values.size(); ++i)
{
    if (i != 0) { std::cout << ", "; }
    std::cout << values[i];
}

ループアンドハーフ:

if (!values.empty())
{
    for (unsigned int i = 0; ; )
    {
        std::cout << values[i];
        ++i;
        if (i == values.size()) { break; }
        std::cout << ", ";
    }
}

後者の構造はより複雑ですが、ほとんどの場合、誤ったチェックを省くことができますi != 0

とは言うものの、コードを素朴な方法で記述したとしても、優れたコンパイラーが部分的な展開を行うことは非常に妥当です。

于 2012-08-30T11:28:01.280 に答える
0

単純なケースでは、私はこの方法を好みます。

if ( ! values.empty())
{
    std::cout << values[0];

    for (size_t z = 1; z < values.size(); z++)
    {
        std::cout << ", " << values[z];
    }
}
于 2012-08-30T18:28:58.233 に答える