ねえ、これは本当に基本的な質問ですが、私はそれについて混乱しました。オブジェクトを作成したとしましょう
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);)である場合、または()から派生した、または( )と同じタイプのコピー初期化である場合:オブジェクトを構築するために、の該当するコンストラクターが選択されます。aTMyClass b = a;T
ご覧のとおり、どちらの例もこのクラスタイプのイニシャライザーのカテゴリに分類されます。
初期化が他の形式のコピー初期化である場合、ユーザー定義の変換シーケンスの後に直接初期化が続くと見なされます。ユーザー定義の変換シーケンスは、基本的に、単一の変換コンストラクターがスローされた標準変換の任意のシーケンスです。
クラス型で、からへの変換コンストラクターがあったc場合、はと同等になります。FooFooMyClassMyClass 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)が呼び出されます(コピーコンストラクターではなく、単純なコピーを呼び出します!)