不清楚复制赋值运算符示例

时间:2016-06-17 09:20:38

标签: c++ c++11

我一直在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;
}

我不明白为什么会这样。不是我们想要实现的第一个例子吗?:复制分配内容。为什么"重新使用相同的字符串对象"?

2 个答案:

答案 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())不需要内存分配/解除分配 - 只复制字符