次のコードについて考えてみます。
#include <iostream>
using namespace std;
class A
{
public:
int a;
A(): a(5)
{
cout << "Constructor\n";
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor\n";
}
A fun(A a)
{
return a;
}
};
int main()
{
A a, c;
A b = a.fun(c);
return 0;
}
上記のコードの出力は次のとおりg++ file.cpp
です。
Constructor
Constructor
Copy Constructor
Copy Constructor
上記のコードの出力は次のとおりg++ -fno-elide-constructors file.cpp
です。
Constructor
Constructor
Copy Constructor
Copy Constructor
Copy Constructor
私は戻り値の最適化を知っています。私の質問は、コピーコンストラクターのどの呼び出しが省略されているかです(返されるときの一時オブジェクトまたは返されたオブジェクトがbにコピーされます)?
省略されたコピーコンストラクターがbの作成に使用されるものである場合、bはどのように作成されますか(この場合もコンストラクター呼び出しがないため)?
行を置き換えて、最初のメソッドまたは2番目のメソッドを使用A b = a.fun(c);
しa.fun(c)
てコンパイルすると、コピーコンストラクターも2回呼び出されます。したがって、前の段落で説明したケースで、一時オブジェクトのコピーコンストラクターが省略されている場合、なぜこの場合は省略されないのでしょうか。
#include <iostream>
using namespace std;
class A
{
public:
int a;
A(): a(5)
{
cout << "Constructing: " << (void *)this << std::endl;
}
A(const A &b)
{
a = b.a;
cout << "Copy Constructor: " << (void *)this << " from " << (void *)&b << std::endl;
}
A fun(A a)
{
return a;
}
};
int main()
{
A a, c;
A b = a.fun(c);
std::cout << "a:" << (void *)&a << std::endl <<
"b:" << (void *)&b << std::endl <<
"c:" << (void *)&c << std::endl;
return 0;
}
収量:
Constructing: 0x7fffbb377220
Constructing: 0x7fffbb377210
Copy Constructor: 0x7fffbb377230 from 0x7fffbb377210
Copy Constructor: 0x7fffbb377200 from 0x7fffbb377230
a:0x7fffbb377220
b:0x7fffbb377200
c:0x7fffbb377210
したがって、中間体(関数の引数)を構築しa
、構築しc
、コピーしてc
から、中間a
体をに直接b
コピーし、通常のaの戻り中間体へのコピーをスキップします。これは、値を渡すとさらによく示されます(に変更A fun(const A& a)
:
Constructing: 0x7fff8e9642b0
Constructing: 0x7fff8e9642a0
Copy Constructor: 0x7fff8e964290 from 0x7fff8e9642a0
a:0x7fff8e9642b0
b:0x7fff8e964290
c:0x7fff8e9642a0
bがfunに渡されていないにもかかわらず、aが構築され、cが構築され、cがbに直接コピーされます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加