短い答え - しないでください。
詳細:
// copy constructor
FeatureValue::FeatureValue(const FeatureValue& other)
{
m_size = other.m_size;
delete[] m_value; // m_value NOT INITIALISED - DON'T DELETE HERE!
m_value = new uint8_t[m_size];
for (int i = 0; i < m_size; i++)
{
m_value[i] = other.m_value[i];
}
}
// assignment operator function
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
FeatureValue(other); // error C2082: redefinition of formal parameter
return *this;
}
ノート:
- コピー コンストラクターが呼び出されると、コピーされるオブジェクトを参照して新しいオブジェクトが構築されますが、既定のコンストラクターはコピー コンストラクターの前に実行されません。これは
m_value
、コピー コンストラクターが実行を開始したときに不確定な値を持つことを意味します。値を代入することはできますが、そこから読み取ることは未定義の動作であり、delete[]
かなり悪いことです (UD よりも悪いことがあるとすれば! ;-))。したがって、そのdelete[]
行を省略してください。
次に、operator=
コピー コンストラクターから機能を利用しようとすると、最初に既存のデータm_value
が指しているすべてを解放する必要があります。ほとんどの人は次のようにしようとします(これは壊れています)-これがあなたがしようとしていたことだと思います:
FeatureValue& FeatureValue::operator=(const FeatureValue& other)
{
// WARNING - this code's not exception safe...!
~FeatureValue(); // call own destructor
new (this) FeatureValue(other); // reconstruct object
return *this;
}
これに関する問題は、FeatureValue の作成が失敗した場合 (たとえばnew
、必要なメモリを取得できないため)、FeatureValue
オブジェクトが無効な状態のままになることです (たとえばm_value
、空間を指している可能性があります)。後でデストラクタが実行されて が実行されると、delete[] m_value
未定義の動作が発生します (プログラムはおそらくクラッシュします)。
あなたは本当にこれにもっと体系的にアプローチする必要があります...それを段階的に書き出すか、おそらく保証された非スローswap()
メソッドを実装します(簡単に実行できます... and だけstd::swap()
m_size
でm_value
、それを ala:
FeatureValue& FeatureValue::operator=(FeatureValue other)
{
swap(other);
return *this;
}
これは簡単でクリーンですが、いくつかの小さなパフォーマンス/効率の問題があります。
既存のm_value
配列を必要以上に長く保持し、ピーク時のメモリ使用量を増やします... を呼び出すことができますclear()
。実際には、問題のデータ構造が膨大な量のデータ (PC アプリの場合は数百メガバイトまたはギガバイト) を保持していない限り、ほとんどの重要なプログラムはこれを気にしません。
既存のm_value
メモリを再利用しようとさえしません-代わりに、常に別new
のことを行いother
ます(メモリ使用量の削減につながる可能性がありますが、常に価値があるとは限りません)。
最終的に、コンパイラが自動的にコピー コンストラクターを作成するのではなく、個別のコピー コンストラクターが存在する可能性がある理由operator=
は、最適に効率的な実装では、一般に、期待どおりに相互に活用できないためです。