请看一下这个程序:
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-&gt; nBlockUse)”
如果我使用aasignment运算符将“Hai”分配给name,则会崩溃。当我使用字符串func _tcscpy将“Hai”分配给name时,它的工作完美。有人可以解释为什么会这样吗?
答案 0 :(得分:4)
name = "Hai";//_tcscpy(name,"Hai");
您没有将“Hai”的内容复制到name
而是name
将指向只读内存(其内容为“Hai”)
如果您稍后尝试删除名称,则可能会崩溃。
答案 1 :(得分:3)
在默认构造函数
中CopyCon()
{
name = new char[20];
name = "Hai";//_tcscpy(name,"Hai");
}
将字符串文字的地址分配给指针,并在析构函数中为其调用delete[]
,这是未定义的行为。 delete[]
只应在new[]
返回的地址上调用。
当您使用_tcscpy()
时,将文字内容复制到new[]
分配的缓冲区,然后析构函数运行正常。
答案 2 :(得分:2)
使用赋值时,将指针name
指向字符串文字“Hai”。稍后会在析构函数中删除它。但是,字符串文字未分配new
,并且不能像这样删除,因此您将获得未定义的行为。您只能使用delete
分配的new
内容解除分配。这与复制构造函数无关。
答案 3 :(得分:2)
name = new char[20];
name = "Hai";//_tcscpy(name,"Hai");
此处您不将数据复制到new
分配的内存中。相反,您要为指针name
指定一个新值,该指针指向只读位置(在大多数情况下)。由于未使用new
分配此内存,因此无法对其进行delete
。另请注意,此处存在内存泄漏,因为永远不会删除使用new char[20];
分配的内存。
答案 4 :(得分: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;
}
我的作品很清楚,而且打字的次数比你少;)
答案 5 :(得分:0)
您在该代码中执行的操作是为名称分配内存块(将地址指定给名称指针)。然后你实际上用字符串文字“Hai”的地址覆盖这个地址(它在构造函数完成后不再存在)。这就是为什么你得到错误,因为析构函数试图释放不属于你的内存。 (你没有分配它。)