使用shared_ptr C ++双重删除错误

时间:2014-01-29 05:21:54

标签: c++ stl shared-ptr

我有以下课程设计:

struct compare{
template <typename T>
bool operator()(const T& a, const T&b){ return *a < *b;}
};

class Trans;

typedef set<shared_ptr<Trans>, compare > TransPointerSet;

class Place{

  // other data members
 TransPointerSet nextTrans;

public:

  // constructor and other methods including overloaded < operator
  void insertNextTrans(shared_ptr<Trans> t){ nextTrans.insert(t); }
  void removeNextTrans() { nextTrans.clear(); }

};

typedef set<shared_ptr<Place>, compare > PlacePointerSet;

class Trans{

//other data members
PlacePointerSet inPlaces;
PlacePointerSet outPlaces;

public:

//constructor and others including overloaded < operator
void insertInPlace(shared_ptr<Place> p){ 
     inPlaces.insert(p); 
     p->insertNextTrans(shared_ptr<Trans>(this)); }
void insertOutPlace(shared_ptr<Place> p){ //body }
void print() cosnt { //body }

};

class Net{
TransPointerSet acts;
//other data members
public:
//constructor and others
};

以下是我测试课程是否正常工作的主要内容。

int main()
{
 shared_ptr<Place> p1 = make_shared<Place>();
shared_ptr<Place> p2 = make_shared<Place>();
shared_ptr<Trans> t = make_shared<Trans>();
t->insertInPlace(p1);
t->insertOutPlace(p2);
t->print();
}

问题是在成功编译后最终会出现问题 在t-&gt; print()正常工作后,“双重免费或损坏(快速顶部)错误”。 我意识到错误在于通过首先将p1作为t-&gt; inPlaces的成员而创建的循环依赖,其插入t作为p1的成员。但我需要这两种方式链接。此外,我试图通过t-&gt; print()之后的方法重置类Place中的nextTrans的每个成员,但由于指针在一个集合中,因此无效。 那么有人可以建议任何方法来解决这个问题吗?

2 个答案:

答案 0 :(得分:6)

这是因为你无法像this一样制作共享指针。通过这样做,您现在有两个共享指向Trans实例的指针,它们都指向同一个实例,但它们带有单独的引用计数器。这意味着两者都会尝试delete指针。

您需要使用std::enable_shared_from_this。链接的参考页面有一个非常好的问题示例。

答案 1 :(得分:4)

Trans::insertInPlace()中的这一行:

p->insertNextTrans(shared_ptr<Trans>(this)); 

创建一个单独的,不相关的共享指针,指向同一个对象。您需要将std::enable_shared_from_this用于Trans类:

class Trans: public std::enable_shared_from_this {
    // ....
};

然后在Trans::insertInPlace()

p->insertNextTrans(shared_from_this());