首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >本例中是否需要重载的operator=?

本例中是否需要重载的operator=?
EN

Stack Overflow用户
提问于 2012-10-10 20:49:13
回答 5查看 120关注 0票数 0

可能重复: What is The Rule of Three?

人们说,如果您需要一个析构函数,那么您实际上需要一个重载的operator=

代码语言:javascript
复制
struct longlife{ };
class z
{
 z(){};
 ~z(){ for( auto it=hold.begin();it!=hold.end() ++it ) delete(*it); };
 vector<longlife*> hold;
};

假设插入到hold上的所有指针都分配了new堆,为什么在这个示例中除了需要解构函数之外,还需要其他什么?

anything else的意思是,

代码语言:javascript
复制
z& operator=( const z&ref )
{
 hold = ref.hold;
 return *this;
}

将:

代码语言:javascript
复制
z a;
a.hold.push_back( heap_item );
z a2;
a2 = a;

因为记忆泄漏?有时很难理解为什么三的规则是规则

EN

回答 5

Stack Overflow用户

回答已采纳

发布于 2012-10-10 20:53:42

不仅需要赋值操作符,还需要实现副本构造函数。否则,编译器将提供默认实现,这些实现将导致两个副本(在赋值/复制构造之后)包含指向相同longlife实例的指针。然后,两个副本的析构函数都会delete这些实例,从而导致未定义的行为。

代码语言:javascript
复制
z a;
a.hold.push_back( heap_item );
z a2;
a2 = a;

a.hold[0]a2.hold[0]都包含指向同一heap_item的指针;因此在销毁过程中会导致双重删除。

避免实现赋值操作符和复制构造函数的简单方法是使用智能指针来保存vector中的vector实例。

代码语言:javascript
复制
std::vector<std::unique_ptr<longlife>> hold;

现在,甚至没有必要为您的类编写析构函数。

对于C++03,您的选项是使用std::tr1::shared_ptr (或boost::shared_ptr)代替unique_ptr或使用boost::ptr_vector (当然,这也是C++11的一个选项)而不是std::vector

票数 3
EN

Stack Overflow用户

发布于 2012-10-10 20:52:08

因为没有赋值操作符和副本构造函数,最终可能会有多个指向同一个堆项的hold向量,导致破坏时未定义的行为:

代码语言:javascript
复制
z firstZ;
if (somethingIsTrue) {
    z otherZ = firstZ;
    // play with otherZ...
    // now otherZ gets destructed, along with longlife's of the firstZ
}
// now it's time to destroy the firstZ, but its longlife's are long gone!

当然,如果使用对象向量或“智能指针”向量,而不是“普通旧”指针的向量,则不会出现此问题。

有关更多信息,请参见http://en.wikipedia.org/wiki/Rule_of_three_%28C++_programming%29

票数 2
EN

Stack Overflow用户

发布于 2012-10-10 20:51:29

实际上这里会有双自由,而不是内存泄漏。

STL容器存储对象,而不是引用。在您的例子中,object是一个指针。指针被简单地复制。您的行a2 = a;将在向量中复制指针。之后,每个析构函数将释放指针。

双自由比内存泄漏危险得多。它会引起令人讨厌的未定义的行为:

代码语言:javascript
复制
MyStruct *p1 = new MyStruct();
delete p1;
.... do something, wait, etc.
delete p1;

同时在另一个线程上:

代码语言:javascript
复制
MyOptherStruct *p2 = new MyOtherStruct();
.... do something, wait, etc.
p2->function();

结果可能是内存分配程序将为p2分配与p1使用的值完全相同的值,因为在第一次调用delete p1之后它是空闲的。稍后,第二个delete p1也会变得很好,因为分配程序认为这是为p2分配的合法指针。这个问题只会出现在p2->function();。看一下线程2的代码,完全不可能理解哪里出了问题以及为什么出错。这是非常难调试的,特别是当系统很大的时候。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12828091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档