我一直在this page上查找一些C ++内容。
关于复制赋值运算符,有以下示例:
Example5& operator= (const Example5& x) {
delete ptr; // delete currently pointed string
ptr = new string (x.content()); // allocate space for new string, and copy
return *this;
}
到目前为止,这一点对我来说很清楚,但文章指出:
甚至更好,因为它的字符串成员不是常量,它可以重用相同的字符串对象:
Example5& operator= (const Example5& x) {
*ptr = x.content();
return *this;
}
我不明白为什么会这样。不是我们想要实现的第一个例子吗?:复制分配内容。为什么"重新使用相同的字符串对象"?
答案 0 :(得分:6)
该页面说明:
[...]隐式版本执行适合的浅拷贝 许多类,但不适用于指向它们处理的对象的类 它的存储,如Example5中的情况。在这种情况下,不仅是 class会产生两次删除指向对象的风险,但是 赋值通过不删除指向的对象来创建内存泄漏 分配前的对象。
让我们再看一遍代码:
#include <iostream>
#include <string>
using namespace std;
class Example5 {
string* ptr;
public:
Example5 (const string& str) : ptr(new string(str)) {}
~Example5 () {delete ptr;}
// copy constructor:
Example5 (const Example5& x) : ptr(new string(x.content())) {}
// access content:
const string& content() const {return *ptr;}
};
因此,复制赋值运算符的隐式版本等同于
Example5& operator= (const Example5& x) {
ptr = x.ptr; // previous value of ptr is lost -> memory leak
return *this;
}
这会导致内存泄漏,因为this.ptr
不会释放元素指针。
建议的版本解除分配ptr
然后为其分配新的内存。取消分配和分配会产生额外的费用和额外的指示,因此第二个代码
Example5& operator= (const Example5& x) {
*ptr = x.content();
return *this;
}
重用(this-&gt; ptr)相同(已分配)的内存区域来存储*x.ptr
的副本。
请注意,由于x.content()
会在x
中返回字符串的副本,*ptr = x.content();
会调用copy assignment operator
的{{1}},其中*ptr
是一个字符串
答案 1 :(得分:1)
与Java和其他一些语言不同,*prt = x.content()
将从x
复制一个字符串。
主要的好处是你不需要为ptr指向的字符串对象删除和重新分配内存(这是非常昂贵的操作),但是使用std:string`s类复制赋值运算符。字符串复制赋值运算符(对于左值引用)也具有强大的异常保证 - 因此,如果在该方法中发生某些事情 - 所有对象的状态将是有效的。并且不要忘记有很大的机会(如果ptr-&gt; length()&lt; = x.content()。length())不需要内存分配/解除分配 - 只复制字符