不检测自赋值的危险???

renheihei 2004-08-30 03:21:25
为什么在重载operator=时需要检测自赋值情况呢?
书上说是不检测的话很危险,能不能举例子说明??
...全文
252 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
insulator 2004-08-31
  • 打赏
  • 举报
回复
class String
{
public:
String(const char *str = NULL); // 普通构造函数
String(const String &other); // 拷贝构造函数
~ String(void); // 析构函数
String & operate =(const String &other); // 赋值函数
private:
char *m_data; // 用于保存字符串
};


String & String::operate =(const String &other)
{
// (1) 检查自赋值
if(this == &other)
return *this;

// (2) 释放原有的内存资源
delete [] m_data;

// (3)分配新的内存资源,并复制内容
int length = strlen(other.m_data);
m_data = new char[length+1]; // 若能加 NULL 判断则更好
strcpy(m_data, other.m_data);

// (4)返回本对象的引用
return *this;
}
Paris_Luo 2004-08-31
  • 打赏
  • 举报
回复
hehe,的确,少写了一句.
短歌如风 2004-08-31
  • 打赏
  • 举报
回复
Paris_Luo的意思是这样:
String::operator=(const String& src)
{
//不检查自赋值,一般代码如下,先释放,后拷贝
delete[] data;
data = new char[strlen(str.data) + 1];//Paris_Luo少写了这一句
memcpy(data,src,strlen(str.data)+1); //自赋值时,拷贝一块已释放的内存!!
return *this;
}

在自赋值发生的时候,代码中的data和str.data其实是同一个,那么在第二句中就访问了在第一句中已经释放了的内存(strlen(str.data),str.data已经释放),这种操作是很危险的。

不过即使没有自赋值的问题,这段代码也有问题:
在data = new char...时是可能产生异常的,然后对象中的data将指向一段没有释放的内存,这个对象已经不能正常工作,甚至不能正常析构。如果在delete[]data之后加一句data = NULL虽然可以解决这个问题,但仍然不好——这样只是保证了对象能使用而没有保证对象状态,一个好的赋值操作符应该在产生异常时保持对象状态与未赋值前一样。正确的实现应该是:
String::operator=(const String& src)
{
char * newdata = NULL;
if (str.data != NULL)
{
newdata = new char[strlen(str.data) + 1];
strcpy(newdata, str.data);
}
delete[] data;
data = newdata;
return *this;
}
这个实现大家可以看到:即使自赋值发生了,仍然不会有问题,只不过做了一些不必要的操作罢了。所以Pari_Luo这个例子并不能说明问题,它在解决了异常安全问题之后就不存在自赋值问题了。
晨星 2004-08-31
  • 打赏
  • 举报
回复
To:楼上
Paris_Luo(不懂)不是都给出例子了吗?
comebaby 2004-08-31
  • 打赏
  • 举报
回复
用new会有怎么样的问题?
能不能举个例子
  • 打赏
  • 举报
回复
呵呵,我也是,一般非对外的接口的类我都 assert , 不过其他的还是判断一下为好
短歌如风 2004-08-30
  • 打赏
  • 举报
回复
我一般不检查自赋值,因为我觉得自赋值是一种很可笑的行为,所以都:
assert(this != &source);
renheihei 2004-08-30
  • 打赏
  • 举报
回复
楼上能不能举个例子?谢谢
ra3 2004-08-30
  • 打赏
  • 举报
回复
主要是对象中有用 new 分配动态内存的情况。
这时不检查自赋值就会出错,如果不用 new 应该不会有什么问题。
  • 打赏
  • 举报
回复
没什么,偶尔coredump而已
Paris_Luo 2004-08-30
  • 打赏
  • 举报
回复
如果成员有指针,而且该指针在重载operator=时,先释放,再拷贝的话,在自赋值时,就会出现问题

例如

class String
{
public:
String(const char*);
String(const String&);
String& oprator=(const String&);
private:
char *data;
};

String::operator=(const String& src)
{
//不检查自赋值,一般代码如下,先释放,后拷贝
delete[] data;
memcpy(data,src,strlen(str.data)+1); //自赋值时,拷贝一块已释放的内存!!
return *this;
}
void main()
{
String str1("hello");
str1 = str1; //错误!
}

64,654

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧