0

オブジェクト コピー コンストラクターの呼び出しを回避することで、Copy ellision と戻り値の最適化がどのように速度を向上させるかについて読んでいます。メカニズムがどのように機能するかは理解していますが、プログラムが期待どおりに動作しない可能性があるのではないかと思いました。

本質的に、私の質問は次のとおりです。別のオブジェクトのコピーであるオブジェクトを作成しないようにコピー コンストラクターを作成するとどうなりますか? 言い換えれば、

AClass original;
AClass copy ( original );
// copy == original -> false

たとえば、次のようなクラスがあるとします。

// AClass.hpp

struct AClass
{
    static int copyCount;
    int copyNumber;

    AClass():copyNumber(0){}
    AClass( AClass const& original ):copyNumber(++copyCount){} // I think this is the signature for the copy constructor
};


// AClass.cpp

int AClass::count ( 0 );

これはクラスに入れるには明らかにひどい振る舞いです。私はこのようなことをすると言っているわけではありません。ただし、ポイントは有効です。コピーの副作用に頼っていたらどうなるでしょうか? この例では、作成したコピーの数を追跡します。最適化がプログラムの実行方法に影響を与えるべきではないと思います。ただし、コピーの省略により、次のコードが失敗する可能性があります。

// Main.cpp

AClass MakeAClass()
{
    return AClass();
}

int main()
{
    AClass copy ( MakeAClass() );

    if ( AClass::copyCount == 1 )
    {
        return 0;
    }
    else
    {
        return -1;
    }
}

これは、最適化なしでデバッグ モードでビルドすると 0 を返す可能性がありますが、最適化をオンにすると突然失敗し、MakeAClass からの戻り値がコピーに直接配置され、コピー コンストラクターがスキップされます。

コンパイラが副作用を探すためにこれらの最適化を試みるときのチェックはありますか? コピーを要求したときにコードがコピーを実行することを期待するのは間違っていますか?

4

1 に答える 1

1

はい。コピー コンストラクター (またはムーブ コンストラクターまたはデストラクター) に副作用がある場合、コピー省略によってコードの動作が変わる可能性があります。

それが要点です。動作を変更できない場合、標準で言及する理由はありません。動作を変更しない最適化は、as-if ルールで既にカバーされています。(1.9/1) つまり:

この国際標準のセマンティック記述は、パラメータ化された非決定論的抽象マシンを定義します。この国際規格は、適合する実装の構造に要件を課していません。特に、抽象マシンの構造をコピーまたはエミュレートする必要はありません。むしろ、以下で説明するように、抽象マシンの観察可能な動作をエミュレートする (のみ) ために、適合する実装が必要です。

コピー省略は、この規則に違反する可能性があるという理由だけで、標準で明示的に言及されています。

于 2014-04-09T04:46:27.913 に答える