4

ここでコピーの初期化と直接の初期化について読んだとき。コピー コンストラクターは、コピーの初期化で呼び出す必要があります。なぜここでコピーコンストラクターが呼び出されないのですか?

#include <iostream>

using namespace std;

class A{};

class B{
public:
B(const A &a){cout << "B construct from A" << endl;}
B(const B &b){cout << "B copy constructor" << endl;}
};

int main(){
A a;
B b = a;
return 0;
}
4

2 に答える 2

5

コピーの初期化はまだコピーの省略の対象であり、それが起こっていることだと思います。理論的には、テンポラリBはから構築されa、コピーコンストラクタはbテンポラリから作成するために使用されます。実際には、コピーを最適化することができます。

これをテストするには、コピーコンストラクターをプライベートにすることができます。

class B{
public:
B(const A &a){cout << "B construct from A" << endl;}
private:
B(const B &b){cout << "B copy constructor" << endl;}
};

コンパイルエラーが発生します。これは、コンパイラーがコピーコンストラクターにアクセスできることを期待しているが、それを呼び出す必要がないことを意味します。

コピーの省略は、観察された動作を変更できる唯一のケースです。

于 2012-10-02T07:30:57.890 に答える
5

これはCopy Elision Ref 1:です。
一時オブジェクトの生成中にコンストラクター呼び出しをコピーすることは、オブジェクトをインラインで作成することによってコンパイラーによって最適化される可能性があり、C++ 標準によって明示的に許可されています。

これは、例とともに標準でもうまく実証されています。

C++03 標準 12.2 一時オブジェクト [class.temporary]
パラ 2:

[Example:
class X {
    // ...
    public:
    // ...
    X(int);
    X(const X&);
    ˜X();
};
X f(X);

void g()
{
    X a(1);
    X b = f(X(2));
    a = f(a);
}

ここで、実装は、 X のコピー コンストラクターX(2)を使用して渡す前に、構築する一時的なものを使用する場合があります。f()あるいは、X(2)引数を保持するために使用されるスペースに構築される場合があります。また、 X f() a=f(a) f(a) a`f(X(2))にコピーする前に結果を保持するためにテンポラリが使用される場合があります。]`b using’s copyconstructor; alternatively,’s result might be constructed in b. On the other hand, the expressionrequires a temporary for either the argument a or the result ofto avoid undesired aliasing of

参照 1:
C++03 12.8 クラス オブジェクトのコピー [class.copy]
パラ 12:

特定の基準が満たされると、オブジェクトのコピー コンストラクターおよび/またはデストラクタに副作用がある場合でも、実装はクラス オブジェクトのコピー構築を省略できます.....

于 2012-10-02T07:36:48.330 に答える