0

次のコードは、を出力するだけA::A()で、A::A(const A&)またはを出力しませんoperator=。なんで?

struct A
{
  A()               { cout << "A::A()" << endl; }
  A(const A& value) { cout << "A::A(const A&)" << endl; }

  A& operator=(const A& newValut)
  {
    cout << "A::operator=" << endl; 
    return *this;
  }
};

A foo()
{
  A a;      //Ok, there we have to create local object by calling A::A().
  return a; //And there we need to copy it, otherwise it will be destroyed
            //because it's local object. But we don't.
}

int main()
{
    A aa = foo(); //Also there we need to put result to the aa
                  //by calling A::A(const A&), but we don't.
}

したがって、このコードは印刷する必要があります

A::A()
A::A(const A&)
A::A(const A&)

しかし、そうではありません。なんで?

最適化なしではfoo()アンダーのインライン化はないことをお勧めします。g++

4

2 に答える 2

10

これは「戻り値の最適化」と呼ばれます。このような場合、コンパイラはコピーを削除することができます。

于 2012-10-14T23:47:52.977 に答える
3

これは、C ++で複合型の戻りが行われる方法です。返されたオブジェクトの場所は、関数を呼び出す前に呼び出し元によって実際に提供され、このまだ初期化されていないオブジェクトへのポインターが関数への非表示の引数として渡されます。関数はこのメモリ位置を使用して、返された式から返されたオブジェクトを作成します。

したがって、返されたオブジェクトがプログラムのように新しいオブジェクトを直接初期化する場合A aa = foo();、戻り値をスタック上のオブジェクトにコピーする必要はありません。この場所に直接オブジェクトを作成するように関数に要求します。したがって、コピーコンストラクターの呼び出しは最大で1回だけ実行されます。(実際、コピーコンストラクターを2回呼び出した場合、C ++コンパイラーは準拠しません)。

これに加えて、コンパイラは「戻り値の最適化」またはRVOと呼ばれる最適化でこの呼び出しを最適化することができます。そんなことがあるものか?コードを見ると、foo()のローカルの「a」変数を戻り値の提案された場所に直接定義できるため、再度コピーする必要がないことがわかります。これは重要な機能です。コピーコンストラクターは複雑で実行に時間がかかる可能性があるため、実装するとパフォーマンスが大幅に向上する可能性があります(そして、私が知っているすべてのコンパイラーはこの機能を実装します)。

したがって、あなたの場合、コンパイラーによっては、コピーコンストラクターへの呼び出しが1回または0回であり、コンパイラーは引き続き準拠しています。

于 2012-10-15T01:06:37.743 に答える