C ++コピーコンストラクトのコンストラクトとアサイン質問
-
20-09-2019 - |
質問
ここで、本「C ++落とし穴」の項目56からの抽出物であります
これは、単純に見ることも珍しくありません Yオブジェクトの初期化が書き込ま 3つの異なる方法のいずれか、かのように 彼らは同等であった。
Y a( 1066 );
Y b = Y(1066);
Y c = 1066;
実際の時点で、これらの3つのすべて 初期化はおそらくなります 同一のオブジェクトコードであります 生成されたが、彼らは同じではないです。 初期化として知られています 直接の初期化、およびそれはありません 正確に1つは期待するかもしれないものを。ザ・ 初期化が行われて Y :: Y(int型)の直接呼び出します。
BおよびCの初期化です より複雑。実際に、彼らはあまりにもです 繁雑。これらは、両方のコピーです 初期化。の場合 Bの初期化、我々が要求しています 匿名の一時の作成 タイプYの値で初期化 1066私たちは、その後、コピーのパラメータとして、この匿名の一時を使用 クラスYを初期化するためのコンストラクタ B。最後に、我々はのためのデストラクタを呼び出します 匿名の一時ます。
これをテストするために、私はデータメンバ(末尾に添付プログラム)との単純なクラスを行なったし、結果は驚くべきものでした。それは本の中で示唆したように、Cの場合のために、オブジェクトがコピーコンストラクタによって構築ではなくたと思われます。
言語規格が変更されたか、これは単にコンパイラの最適化機能である場合は、誰もが知っていますか?私は、Visual Studio 2008を使用していました。
コードサンプルます:
#include <iostream>
class Widget
{
std::string name;
public:
// Constructor
Widget(std::string n) { name=n; std::cout << "Constructing Widget " << this->name << std::endl; }
// Copy constructor
Widget (const Widget& rhs) { std::cout << "Copy constructing Widget from " << rhs.name << std::endl; }
// Assignment operator
Widget& operator=(const Widget& rhs) { std::cout << "Assigning Widget from " << rhs.name << " to " << this->name << std::endl; return *this; }
};
int main(void)
{
// construct
Widget a("a");
// copy construct
Widget b(a);
// construct and assign
Widget c("c");
c = a;
// copy construct!
Widget d = a;
// construct!
Widget e = "e";
// construct and assign
Widget f = Widget("f");
return 0;
}
出力:
Constructing Widget a
Copy constructing Widget from a
Constructing Widget c
Assigning Widget from a to c
Copy constructing Widget from a
Constructing Widget e
Constructing Widget f
Copy constructing Widget from f
私はDとEを構築した結果によって、最も驚きました。正確に言うと、私は空のオブジェクトが作成されるように期待していた、そしてそのオブジェクトが作成され、空のオブジェクトに割り当てられます。実際には、オブジェクトがコピーコンストラクタによって作成された。
解決
構文
X a = b;
AとBがタイプXのあるところには必ずコピーの建設を意味しています。
次のようなものは何でも変異体、X a = X();
使用され、そこに起こって何も代入されていない、とされていない決して。構築し、のようなものになるでしょう割り当てます:
X a;
a = X();
他のヒント
コンパイラはb
と同じになるようにケースc
とa
を最適化することが許されます。さらに、コピーの構築と代入演算子の呼び出しは完全にとにかく、コンパイラによって排除することができますので、あなたが見るものは何でも、必ずしも異なるコンパイラ、あるいはコンパイラ設定で同じではありません。
C ++ 17のように、これらの3つのすべての<全角>なぜなら、多くの場合、<のhref = "HTTPと呼ばれるものの(Y::Y(int)
は、単にexplicit
を許可しませんc
、でない限り)の等価です:// en.cppreference.com/w/cpp/language/copy_elision」のrel = "nofollowをnoreferrer">必須コピーの省略するます。
Y c = 1066;
への暗黙的な変換の結果はY
を初期化するのではなく、一時的に作成するために使用されるprvalueあるため、でさえY
は一c
オブジェクトを作成します。