2010-07-24 30 views
3

说我有两个容器存储指向相同的对象:从STL容器中移除元素时调用析构函数吗?

std::list<Foo*> fooList; 
std::vector<Foo*> fooVec; 

比方说,我通过一个,如果它的方法去除从这些容器中的一个对象:

std::vector<Foo*>::iterator itr = 
    std::find(fooVec.begin(), fooVec.end(), pToObj); 
fooVec.erase(itr); 

CppReference说,这个电话对象的析构函数。这是否意味着指向fooList中的对象的指针是一个悬挂指针?

我不想使用引用计数的指针。这个问题怎么处理?

+1

使用引用计数的指针。这就是他们的目的。 – Puppy 2010-07-24 18:31:54

回答

6

当您从容器中取出一个指针,你所做的一切是采取从容器中的指针值,没有被删除。 (即:指针没有析构函数)。

但是,容器中的指针是很危险的。考虑:

std::vector<int*> v; 
v.push_back(new int()); 
v.push_back(new int()); 
v.push_back(new int()); 

如果您从未通过容器并删除每个容器,则已泄漏。更糟的是它不是特例安全。您应该使用pointer container,这将删除它们在被擦除时指向的内容。 (当容器破坏时,所有东西都会被擦除。)

但是,就你而言,由于你在不同的地方共享一个指针,所以我看不到针对shared_ptr的参数;这正是它所做的。

+0

请为我解决这个问题。为什么list :: erase的文档会说''这会通过删除的元素数量有效地减少容器的大小,这些元素被销毁。“#http://www.cplusplus.com/reference/list/list/erase/ – matrixugly 2016-09-02 18:15:24

+0

@matrixugly :你应该使用cppreference,它更好:http://en.cppreference.com/w/cpp/container/list/erase。正如它在那里澄清的那样,有两种“擦除”重载。我们需要一系列迭代器,并且每个元素都会被擦除。 – GManNickG 2016-09-03 04:07:28

1

我不认为该对象的析构函数会被调用。 fooList中的指针仍应指向有效数据。

如果您指的是this link,它是在讨论如何调用erase会使您指向向量中后续位置的任何迭代器失效。但是使迭代器无效与在向量中的一个事物上调用delete不同。

0

当您有一个指向对象的原始指针时,除非删除它,否则不会调用析构函数。

您可以用来确保您的对象在正确的时间被删除并使用指针容器(如许多算法所需)的模式(或者它是一个成语?)是使用单独的双端存储器来存储实际的物体。您必须确保在任何指针容器后deque都被销毁。你应该使用deque而不是vector的原因是你可以添加对象到deque而不会使指向先前存储对象的指针失效。

0

两个容器都持有对(Foo *)对象的引用 - 所以如果析构函数被调用,它就是指针对象的析构函数(可能什么也不做),而不是Foo对象本身。原始对象(类Foo)不被破坏,因此没有悬挂引用。

0

在您的情况下,存储在容器中的对象是原始指针的副本,而不是原始指针。因此,对于您决定存储的每个Foo*,您都将有3个指针(原始文件,fooList中的一个和fooVec中的一个),全部指向内存中的相同位置。 所以当你调用erase时,删除将在指针本身而不是它指向的内容上被调用,并且指针上的删除是没有操作的(它们没有像GMan说的那样的析构函数)。

相关问题