2

このプログラムを見てください:

class CopyCon
{
public:
char *name;

CopyCon()
{ 
    name = new char[20];        
    name = "Hai";//_tcscpy(name,"Hai");
}

CopyCon(const CopyCon &objCopyCon)
{
    name = new char[_tcslen(objCopyCon.name)+1];
    _tcscpy(name,objCopyCon.name);
}

~CopyCon()
{
    if( name != NULL )
    {
        delete[] name;
        name = NULL;
    }
}
};

int main()
{
    CopyCon obj1;
    CopyCon obj2(obj1);
    cout<<obj1.name<<endl;
    cout<<obj2.name<<endl;
}

このプログラムは実行時にクラッシュします。エラー: 「式: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse)」

割り当て演算子を使用して名前に「はい」を割り当てると、クラッシュします。文字列 func _tcscpy を使用して「Hai」を名前に割り当てると、完全に機能します。誰かがその理由を説明できますか?

4

6 に答える 6

4
 name = "Hai";//_tcscpy(name,"Hai");

「Hai」の内容をコピーするのではなくnamename後で名前を削除しようとすると、読み取り専用メモリ (その内容は「Hai」) を指し、クラッシュする可能性があります。

于 2010-06-07T08:20:41.380 に答える
3

デフォルトのコンストラクタで

CopyCon()
{ 
    name = new char[20];        
    name = "Hai";//_tcscpy(name,"Hai");
}

文字列リテラルのアドレスをポインターに割り当て、それを呼び出すデストラクタdelete[]で、これは未定義の動作です。delete[]によって返されたアドレスでのみ呼び出す必要がありますnew[]

代わりに使用すると_tcscpy()、によって割り当てられたバッファにリテラルコンテンツをコピーするnew[]と、デストラクタが正常に実行されます。

于 2010-06-07T08:21:27.807 に答える
2

まったく同じプログラムですが、C++ では次のようになります。

struct CopyCon
{
  CopyCon(): name("HAI") {}
  std::string name;
};

int main(int argc, char* argv[])
{
  CopyCon obj1;
  CopyCon obj2(obj1);
  cout<<obj1.name<<endl;
  cout<<obj2.name<<endl;
}

私の作品は明確で、私はあなたがしたよりも少ないタイプを入力しました;)

于 2010-06-07T08:49:04.183 に答える
2

代入を使用するときは、ポインターnameが文字列リテラル "Hai" を指すようにします。これは後でデストラクタで削除されます。ただし、文字列リテラルは で割り当てられておらnewず、このように削除できないため、未定義の動作が発生します。deleteで割り当てたもののみを解放できますnew。これは、コピー コンストラクターとは関係ありません。

于 2010-06-07T08:20:39.367 に答える
2
name = new char[20];        
name = "Hai";//_tcscpy(name,"Hai");

ここでは、によって割り当てられたメモリにデータをコピーしていませんnewname代わりに、読み取り専用の場所を指すポインターに新しい値を割り当てています (ほとんどの場合)。このメモリは使用して割り当てられていないため、new実行できませんdeletenew char[20];また、使用して割り当てられたメモリは削除されないため、ここでメモリ リークが発生することに注意してください。

于 2010-06-07T08:24:41.527 に答える
0

そのコードで行うことは、名前にメモリ ブロックを割り当てることです (名前ポインタにアドレスを割り当てます)。次に、このアドレスを文字列リテラル "Hai" (コンストラクターの終了後に存在しなくなります) のアドレスで実際に上書きします。デストラクタがあなたに属していないメモリを解放しようとするため、エラーが発生するのはそのためです。(あなたはそれを割り当てませんでした)。

于 2010-06-07T08:22:55.990 に答える