ねえ、これは本当に基本的な質問ですが、私はそれについて混乱しました。オブジェクトを作成したとしましょう
MyObject a
。
コピーコンストラクターが付属しているので、これができることはわかっています。
MyObject b(a);
しかし、私はこれを行うことができますか?
MyObject& b(a);
そして私がこれを行う場合:
MyObject b = a;
何が入っていb
ますか?この質問が基本的すぎて投稿に煩わされない場合は、お詫び申し上げます。
ねえ、これは本当に基本的な質問ですが、私はそれについて混乱しました。オブジェクトを作成したとしましょう
MyObject a
。
コピーコンストラクターが付属しているので、これができることはわかっています。
MyObject b(a);
しかし、私はこれを行うことができますか?
MyObject& b(a);
そして私がこれを行う場合:
MyObject b = a;
何が入っていb
ますか?この質問が基本的すぎて投稿に煩わされない場合は、お詫び申し上げます。
行うことMyObject& b(a)
は、コピーコンストラクターとは何の関係もありません。b
オブジェクトへの参照であるものを作成するだけa
です。何もコピーされません。b
オブジェクトのエイリアスと考えてくださいa
。b
それ以降は、a
同じオブジェクトを参照するために使用できます。
MyObject b = a;
と同じように、コピーコンストラクタを使用しますMyObject b(a);
。
初期化には2つの形式があります。コピー初期化T x = a;
として知られています。直接初期化として知られています。T x(a)
T x{a}
が参照型の場合T
、どのタイプの初期化を使用するかは関係ありません。どちらも同じ効果があります。
T
がクラスタイプの場合、2つの可能性があります。
初期化が直接初期化(MyClass b(a);
)である場合、または()から派生した、または( )と同じタイプのコピー初期化である場合:オブジェクトを構築するために、の該当するコンストラクターが選択されます。a
T
MyClass b = a;
T
ご覧のとおり、どちらの例もこのクラスタイプのイニシャライザーのカテゴリに分類されます。
初期化が他の形式のコピー初期化である場合、ユーザー定義の変換シーケンスの後に直接初期化が続くと見なされます。ユーザー定義の変換シーケンスは、基本的に、単一の変換コンストラクターがスローされた標準変換の任意のシーケンスです。
クラス型で、からへの変換コンストラクターがあったc
場合、はと同等になります。Foo
Foo
MyClass
MyClass b = c;
MyClass b(MyClass(c));
したがって、基本的に、送信元と宛先のタイプが同じである場合、初期化の両方の形式は同等です。変換が必要な場合は、そうではありません。これを示す簡単な例は次のとおりです。
#include <iostream>
struct Bar { };
struct Foo
{
Foo(const Foo& f) { std::cout << "Copy" << std::endl; }
Foo(const Bar& b) { std::cout << "Convert" << std::endl; }
};
int main(int argc, const char* argv[])
{
Bar b;
Foo f1(b);
std::cout << "----" << std::endl;
Foo f2 = b;
return 0;
}
このプログラムの出力(コピーの省略が無効になっている場合)は次のとおりです。
Convert
----
Convert
Copy
もちろん、他の種類の初期化もたくさんあります(リストの初期化、文字配列、集計など)。
これが私の見解です:
参照は他の誰かのストレージに関連付けられています。参照にアクセスするときはいつでも、そのストレージにアクセスしています。参照は単なるエイリアスであるため、nullに割り当てることはできません。参照は、作成時に初期化する必要があります。(ポインタはいつでも初期化できます。)
だからあなたが言うとき
MyObject& b(a);
コンパイラーはストレージbの一部を割り当て、参照をaに結び付けます。
あなたが言う時
MyObject b = a;
aの参照をコピーコンストラクターに渡し、そこから新しいbを作成します。コピーコンストラクターが作成されている場合にのみ、ディープコピーであることに注意してください。それ以外の場合は、デフォルトのコピーコンストラクターを呼び出し、結果として浅いコピーになります。
そしてあなたが言うとき
a = b; // after creating these objects
Object :: operator =(const Object&)として変換されるため、A.operator =(B)が呼び出されます(コピーコンストラクターではなく、単純なコピーを呼び出します!)