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)”

如果我使用 aasignment 运算符将“Hai”分配给名称,它就会崩溃。当我使用 string func _tcscpy 将“Hai”分配给名称时,它工作得很好。有人可以解释为什么会这样吗?

4

6 回答 6

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

如果您稍后尝试删除名称,则您没有将“Hai”的内容复制到其中,name而是name指向只读存储器(其内容为“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

当您使用赋值时,您将指针name指向字符串文字“Hai”。这稍后会在析构函数中被删除。但是,字符串文字没有被分配new,并且不能像这样被删除,所以你会得到未定义的行为。您只能取消分配delete您分配的东西new。这与复制构造函数无关。

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

在这里,您不是将数据复制到由new. name相反,您正在为指向只读位置的指针分配一个新值(在大多数情况下)。由于此内存不是使用分配的,因此new您无法delete对其进行操作。另外,请注意这里有内存泄漏,因为使用分配的内存new char[20];永远不会被删除。

于 2010-06-07T08:24:41.527 回答
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 回答
0

您在该代码中所做的是为名称分配一个内存块(为名称指针分配一个地址)。然后你实际上用字符串文字“Hai”的地址覆盖了这个地址(在构造函数完成后它不再存在)。这就是为什么你得到错误,因为析构函数试图释放不属于你的内存。(你没有分配它)。

于 2010-06-07T08:22:55.990 回答