【问题标题】:C++ operator overloads and destructorsC++ 运算符重载和析构函数
【发布时间】:2012-03-26 07:12:17
【问题描述】:
struct Node
{
int value
Node* next;
}
typedef List Node*

const Set operator +(const Set& a, const Set& b)
{
    Set aSet;
    List newList = mergeListsCopy(a.list, b.list);
    aSet.list = newList;
    return aSet;
}

class Set
{
public:
//method decs
private:
    List list;
};

Set::~Set()
{
    list = deleteList(list);    
}

这段代码的内部工作非常好,mergeListsCopy 从两个单链表创建一个新列表,并将指针分配给作为 aSet 私有变量的列表。

问题是当 aSet 返回时,aSet.list 是一些奇怪的毒地址(在本例中为 0xf)。

当我通过调试器运行它时,在运算符重载的范围内创建了一个 Set,但是在本地也使用符号 aSet 创建了对该 set 的两个引用,在返回发生之前,程序跳转到析构函数,大概是针对无关的 Set,但由于只有一个 Set,因此它会被销毁。

当我注释掉我的析构函数时,这个问题就消失了。我做错了什么?

【问题讨论】:

  • NB 运算符方法是朋友使用的函数调用工作。

标签: c++ reference operator-overloading destructor


【解决方案1】:

您需要关注Rule of Three

如果您需要自己显式声明析构函数复制构造函数复制赋值运算符,您可能需要显式声明所有三个其中。

在程序执行过程中很可能会创建临时无名对象(通过调用隐式编译器生成的复制构造函数),当这些临时对象通过调用析构函数被销毁时,它最终会弄乱你的链表。

【讨论】:

  • 所以如果我有一个析构函数,那么除非我也提供一个复制构造函数,否则它就无法工作?我很困惑。我想我还应该提到我已经指定了一个默认构造函数,它只是将 Set.list 设置为 NULL。
  • 实际上,您需要将 三规则 应用到您的两个课程 SetNode 以及(我相信它需要声明您自己的上面提到的三巨头)。这里看到的问题是由于没有将规则三应用于Set 类。
  • @awiebe:你没有提供拷贝构造函数!复制构造函数在临时对象创建期间创建指针的浅表副本(按值传递等),该副本在调用析构函数时被进一步破坏,从而使您的实际对象无效并使您的实际对象成为悬空指针。您将需要提供一个复制构造函数来处理所涉及的指针的深层副本。
  • @awiebe:不一定非要深拷贝。如果您要按值传递 Set,则对列表进行引用计数可能更可取。此外,如果您可以使用 C++11,则只能提供接管和删除复制构造函数的移动构造函数。你仍然可以按值使用临时对象,但要避免任何隐式深拷贝。
猜你喜欢
  • 1970-01-01
  • 2013-02-06
  • 2011-10-11
  • 2016-07-21
  • 1970-01-01
  • 2011-06-29
  • 1970-01-01
  • 1970-01-01
  • 2013-10-08
相关资源
最近更新 更多