作者:可爱竹子16 | 来源:互联网 | 2023-05-18 10:53
在自己写的CString类中,包含着一个char*string成员,析构函数如下~CString{if(string!NULL){deletestring;s
在自己写的CString类中,包含着一个char *string成员,析构函数如下
~CString
{
if(string!=NULL)
{
delete string;
string=NULL;
}
}
但是在执行如下代码
CString str1="123";
CString str2;
str2=str1;
后;
str1和str2的string指针都指向了同一块内存,在析构这两个对象时,析构str1,便已经把这块内存delete,并将其指针指向了NULL,可是str2的指针依旧指向这块被释放的内存,成了野指针。
请问有什么办法可以解决这个问题?
19 个解决方案
1. CString 赋值的是后自己 new 一块内存出来, 把字符串 strcpy 过来,而不是只改指针的指向.
2. 用引用计数.
str1创建个临时对象赋给str2
所以不是一个地址
你可以调试看看str1和str2的地址会发现是不一样的
不是 str1 和 str2 的地址, 是他们里面的 string 成员的地址.
operator= 应该类似于这样的实现:
CString& CString::operator=(const CString& rhs)
{
if(this == &rhs)
return *this;
if(string)
delete string;
string = new char[strlen(rhs.string) + 1];
strcpy(string, rhs.string, ...);
return *this;
}
复制的时候要连string所指向的内容一起复制。也就是说要先new一块地盘,把源中string所指字符串复制进去,再将目的中string指向它。
这样析构就不会有问题了。
如果觉得舍不得内存,那就要更改string所指向的结构了,改起来麻烦些。具体是在string所指位置放上一个结构,其中包含一个真正指向字符串的指针和一个引用计数器。每当一个字符串被复制时,将该计数增量。析构时首先减量,减至0才回收这个结构及其所指字符串。
如没有特殊要求,何不用指针代替类型?
CString *st2 = &st1; //用引用也一样
对于复杂的结构或类,如果不希望给自己添麻烦,那还是用指针来的安全高效
auto_ptr share_ptr 或者自己实现引用计数 或者自己实现全拷贝
你重载复制操作符=的时候,为什么不新开辟内存给str1 呢?