まず、次の文字列クラスの実装に問題がないか確認してみましょう。
class String
{
char* _str;
public:
String(const char* str = "")
{
// 构造string类对象时,如果传递nullptr指针,认为程序非法,此处断言下
if(nullptr == str)
{
assert(false);
return;
}
_str = new char[strlen(str) + 1];
strcpy(_str, str);
}
~String() {
if(_str) {
delete[] _str;
_str = nullptr;
}
}
};
// 测试
void TestString() {
String s1("hello bit!!!");
String s2(s1);
}
上記のStringクラスは、そのコピーコンストラクターと代入演算子のオーバーロードを明示的に定義していません。このとき、コンパイラーはデフォルトを合成します。s1を使用してs2を作成すると、コンパイラーはデフォルトのコピー構成を呼び出します。最終的に発生する問題は、s1とs2が同じメモリ空間を共有し、解放中に同じ空間ブロックが複数回解放され、プログラムがクラッシュすることです。このコピー方法は、浅いコピーと呼ばれます。
浅いコピー
浅いコピー:ビットコピーとも呼ばれ、コンパイラはオブジェクトの値をコピーするだけです。場合は、オブジェクトの経営資源、そして最終的にそれがされます、同じリソースを共有する複数のオブジェクトにつながるオブジェクトが破棄されたときに、そう、他のオブジェクトがリソースを解放したことを知らない場合、それも有効である時に、リソースを解放しますリソースの操作を続行すると、アクセス違反が発生します。浅いコピーの問題を解決するために、ディープコピーがC ++で導入されました。
深いコピー
リソース管理がクラスに関与している場合、そのコピーコンストラクター、代入演算子のオーバーロード、およびデストラクタを明示的に指定する必要があります。通常、ディープコピーの形式で提供されます。