3

我有一个包含指针的类,该类什么都不继承

class MyClass
{
public:
MyClass();
~MyClass();

private:
//i have pointers here
};
MyClass::~MyClass()
{
print("destroyed..");
}

现在我必须使用这个类作为向量中的指针,如下所示:

vector<MyClass*> classes;

在这里推送一些类,但是当我删除一个元素时:

classes.remove(index);

没有调用析构函数,我认为我有内存泄漏。
那么我如何让它调用析构函数

4

7 回答 7

3

delete指针向量在从指针中删除或清除时​​对指针没有任何作用。向量无法知道指针是否是动态分配的。打电话不是工作delete

如果有必要,您可以调用delete指针。您的问题中没有足够的详细信息来确定是否有必要(您没有显示指向的对象是如何分配的)。但是由于您声称存在内存泄漏,这可能表明它们是动态分配的。直接的解决方案是调用删除:

delete *it;
classes.erase(it); // vector has no remove member function

更安全的解决方案是存储唯一所有权智能指针,例如std::unique_ptr<MyClass>. 标准库还为共享所有权和弱所有权提供了智能指针。请参阅智能指针

以上所有内容都假设您确实需要存储一个指针。一般来说,存储值更安全、更清晰:

std::vector<MyClass> classes; // but don't call it "classes". A vector stores objects.
于 2013-09-09T06:27:50.300 回答
2

这就是为什么您应该std::vector<MyClass*>首先避免使用的原因之一。有一个丑陋的内存管理与之相关,它不会像以前那样简单classes.remove(index);

基本上,对于每new一个 a都delete必须被调用,对于每new[]一个 adelete[]必须被调用,不管你是使用这个指针作为一个局部变量还是你把它放入向量中:

vector<MyClass*> vec;
vec.push_back(new MyClass());     // <-- object has been created
...
delete classes[index];            // <-- object shall be destructed
// the delete call will automatically invoke the destructor if needed
...
// now you can remove the dangling pointer from the vector

请注意,一旦对象被破坏,对该对象的任何(旧)引用都是无效的,并且尝试使用此类引用(悬空指针)访问该对象将产生未定义的行为

于 2013-09-09T06:31:13.260 回答
1

首先,std::vector没有remove,你可能的意思是erase

其次,您需要手动调用delete要删除的任何内容:

vector<MyClass*> classes;
auto iter = <iterator to index to remove>;
delete *iter;;
classes.erase(iter);

或者,为了避免所有这些痛苦,请使用std::unique_ptr<MyClass>.

于 2013-09-09T06:30:51.377 回答
0

在将其从向量中删除之前,创建一个指向孔 MyClass* 指针的临时指针。

vector<MyClass*> classes;

//push some classes in here but
//when i remove an element
MyClass* temp = classes[index];
classes.remove(index);

// call delete temp;  if you want to call the destructor thus avoid memory leak.
delete temp;

为避免内存泄漏,请记住永远不要放松对堆对象的控制,始终在对象释放之前保留一个指针或对它的引用。

于 2013-09-09T06:32:51.630 回答
0

目前还不清楚谁负责管理内部指针指向的对象的生命周期classes。你是把newed指针压进去了,还是把自动存储对象的地址压进去了?

如果您已经完成了前者,那么您必须delete在删除它之前手动指针。否则,如果您已经完成了后者,那么您可以保持原样,只是让指向的对象在它们离开各自的范围时自行破坏。如果你混合了newed 和 non new-ed 指针,它们的可能性并不像你想象的那么遥远,那么你肯定是该死的,未定义的行为让恶魔飞出你的鼻子。

这类涉及指针的情况是非常模糊的,一般建议不要使用指针,而将std::vector对象存储为普通对象,这样可以使您的对象生命周期管理更加简单,并且声明本身就说明了一切。

vector<MyClass> classes;  // Do this instead
于 2013-09-09T06:32:53.750 回答
0

您必须在应用程序退出之前或在您的类对象从vector.

// Delete all
vector<MyClass*>::iterator it = classes.begin();
while (it != classes.end()) {
    delete *it;
    it = classes.erase(it);
}

提示切勿添加堆栈构造的指针,如下所示:

MyClass m;
classes.push_back(&m);

编辑:正如其他成员所建议的,更好的解决方案是:

MyClass m(/* ... */);
vector<MyClass> classes;
classes.push_back(m);

但是请注意,您必须正确实现复制构造函数,特别是如果您的类具有使用 new 创建的指针数据成员。

于 2013-09-09T06:31:06.960 回答
0

您似乎希望您的矢量成为您的项目的经理。
看一下 boost::ptr_vector 类,
它基本上是 std::vector 类的包装器。
你声明这个向量是这些指针的“持有者”,如果你从这个容器中删除它们,你希望它们被删除。

#include <boost/ptr_container/ptr_vector.hpp>
...
boost::ptr_vector<MyClass> myClassContainer;  
myClassContainer.push_back(new MyClass());
myClassContainer.clear(); // will call delete on every stored object!
于 2013-09-09T08:18:59.797 回答