C++コピー構築関数とコピー付与演算子

8325 ワード

コピーコンストラクタ
コピーコンストラクション関数は、同じタイプの別のオブジェクトで新しいオブジェクトを初期化するときに何をするかを定義します.コンストラクション関数の最初のパラメータが自分のクラスタイプの参照であり、追加のパラメータにデフォルト値がある場合、このコンストラクション関数はコピーコンストラクション関数です.コピーコンストラクション関数のパラメータタイプはconst参照が望ましい.
クラスにコピーコンストラクタを定義していない場合、コンパイラはデフォルトコンストラクタを合成するのとは異なり、他のコンストラクタを定義しても、コンパイラはコピーコンストラクタを合成します.
一般的に、合成されたコピーコンストラクタは、そのパラメータのメンバーを作成中のオブジェクトに個別にコピーし、クラスタイプのメンバーでは、そのコピーコンストラクタを使用してコピーします.組み込み型のメンバーは直接コピーします.配列タイプのメンバーは、配列要素を1つずつコピーします.
ダイレクト初期化とコピー初期化
直接初期化を使用する場合、コンパイラはパラメータに最も一致するコンストラクション関数を使用して初期化されます.コピー初期化を使用すると、コンパイラは右側の演算オブジェクトを作成中のオブジェクトにコピーし、必要に応じてタイプ変換を行います.
コピー初期化は、通常、コピーコンストラクション関数を使用して行われますが、モバイルコンストラクション関数を使用する場合もあります.
std::string str1(10,'h');//     
std::string str2(str1);//     
std::string str3 = "hello";//     
std::string str4 = std::string(10, 'h');//     

コピーの初期化
  • =変数を定義する場合.
  • は、オブジェクトを実パラメータとして非参照タイプのパラメータに渡す場合、コピーコンストラクション関数自体のパラメータが参照タイプでなければならない理由を説明し、パラメータが参照タイプでなければデッドループに陥る理由を説明します.
  • は、戻りタイプが非参照タイプの関数からオブジェクトを返す場合.
  • 配列内の要素または集約クラス内のメンバーをカッコリストで初期化する場合.
  • 標準ライブラリコンテナがinsertまたはpushを呼び出してメンバーを追加する場合.

  • コピー代入演算子
    コピー付与演算子は、同じタイプの別のオブジェクトにオブジェクトを付与するときに何をするかを定義します.コピーコンストラクタと同様に、クラスが独自のコピー付与演算子を定義していない場合、コンパイラは1つを生成します.
    代入演算子を再ロードすると、コピー代入演算子を定義できます.代入演算子は、組み込みタイプの代入値と一致するように、左側の演算オブジェクトへの参照を返します.
    class Person
    {
    public:
    	const char* name_;
    	Person(const char* name):name_(name) {};
    	Person& operator=(const Person& person);
    };
     
    Person& Person::operator=(const Person& person)//       
    {
    	std::cout << "call Person::operator=" << std::endl;
    	name_ = person.name_;
    	return *this;
    }
     
    
    int main(void)
    {
    	Person person1("xiao hong");
    	Person person2("xiao ming");
    	person1 = person2;
    	system("pause");
    	return 0;
    }
    

    構造関数が必要なクラスもコピーと付与操作が必要です
    クラスが構造関数を必要とする場合、データ・メンバーが構造関数(newから出たポインタなど)で解放されると、コピーまたは付与時にコピーされ、構造関数を実行すると2回解放されるため、コピーおよび付与操作も必要です.
    コピー操作が必要なクラスも値付け操作が必要です.逆も同様です.
    コピーコンストラクション関数が新しく作成したオブジェクトごとにユニークなシーケンス番号を生成する必要があると仮定すると、オブジェクトにシーケンス番号を付与するのを避ける必要があります.したがって、クラスがコンストラクション関数をコピーする必要がある場合、このクラスの多くの場合、付与演算子も必要です.
    使用=default
    コンストラクション関数と同様に、=defaultでコンパイラに合成されたコピーコンストラクション関数と合成された付与演算子を明示的に生成することもできます.同様に、=defaultがクラス内宣言に表示される場合、それはインラインであり、クラス外定義ではありません.
    class Person
    {
    public:
    	const char* name_;
    	Person(const char* name):name_(name) {};
    	Person(const Person& person) = default;
    	Person& operator=(const Person& person)=default;
    };