【问题标题】:Copy constructor, assignment operator, and destructor code duplication复制构造函数、赋值运算符和析构函数代码重复
【发布时间】:2015-01-04 20:51:09
【问题描述】:

我了解深拷贝的必要性,并且为了确保我的代码按预期运行,我正在为我的班级编写一个拷贝 ctor、赋值运算符和 dtor。

但是,在我看来,在任何情况下,赋值运算符都必须首先执行析构函数的工作(释放任何动态分配的内存,以防止内存泄漏),然后是复制构造函数的工作(制作所有动态分配的数据并将其复制到正在构建的实例中)。

是否存在赋值运算符在概念上应该做以下事情以外的事情的情况?

class SomeClass{
    //member data, copy ctor, dtor
    SomeClass& operator=(SomeClass const& rhs){
        //what the destructor does
        //what the copy constructor does
    }
};

代码实际上是相同的,重写似乎是在浪费时间。除了直接在赋值运算符的开头调用析构函数之外,我想不出一种方法来重用我已经编写的复制构造函数代码,因为我相信做类似

*this=rhs

只会递归调用赋值运算符,因为从技术上讲,“this”已经被构造了。

【问题讨论】:

  • 我认为这应该可以回答你所有的问题:What is copy-and-swap?
  • C++-faq 的自我分配部分也简要介绍了这一点。另见Rule of Three。要回应@JohnDibling 的评论,请参阅Rule of Zero
  • 理想情况下,在设计良好的类中,您根本不需要构造函数、复制赋值运算符或析构函数。除非你需要一个虚拟析构函数,但即便如此它也应该是微不足道的。
  • 谁知道vectorunique_ptr 是设计如此糟糕的类!
  • 我并不是说零规则是坏的或错误的。我只是说它不是普遍正确的,并且认为不遵循它表示糟糕的设计的建议是荒谬的。

标签: c++


【解决方案1】:

如 cmets 中所述,您对代码重复的担忧已通过应用 copy-and-swap idiom 得到解决:

class SomeClass{
    //member data, copy ctor, dtor
    SomeClass& operator=(SomeClass rhs){
        swap(*this, rhs);
        return *this;
    }
    friend void swap(SomeClass& first, SomeClass& second) {
        using std::swap;     
        swap(first.data, second.data);
        //... etc. for other data members
    }
};

您必须实现额外的swap 函数,但您的复制构造函数和析构函数代码会以自然的方式重用。复制构造函数在赋值源传递给赋值运算符时使用,析构函数在赋值运算符返回时析构参数时重用。

【讨论】:

  • 这个答案如果还显示了复制构造函数的实现会更完整。
  • 复制构造函数的实现是根据 OP 假设的。
猜你喜欢
  • 1970-01-01
  • 2011-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-12
  • 2013-04-13
  • 1970-01-01
相关资源
最近更新 更多