如果我有以下代码,
Foo *f = new Foo();
vector<Foo*> vect;
vect.push_back(f);
// do stuff
vect.erase(f);
我是否创建了内存泄漏? 我想是的,但是 erase 这个词让人感觉它正在删除它。
写这个,我想知道将指针放在STL向量中是不是错误。你觉得怎么样?
答案 0 :(得分:8)
是的,你创建了内存泄漏。 std :: vector和其他容器只会删除指针,它们不会释放指针指向的内存。
将指针放入标准库容器中并不罕见。但问题是,从容器中删除时必须跟踪删除它。更好,更简单的方法是使用boost :: shared_ptr:
{
boost::shared_ptr<foo> f(new foo);
std::vector< boost::shared_ptr<foo> > v;
v.push_back(f);
v.erase(v.begin());
} /* if the last copy of foo goes out of scope, the memory is automatically freed */
下一个C ++标准(通常称为C ++ 1x和C ++ 0x)将包含std::shared_ptr
。在那里,您还可以使用速度更快的std::unique_ptr<T>
,因为它不允许复制。将std::unique_ptr
与c ++ 0x中的容器一起使用类似于boost中的ptr_container
库。
答案 1 :(得分:4)
另一种选择是使用Boost Pointer Containers。它们的设计完全符合您的要求。
答案 2 :(得分:2)
另外还有boost :: ptr_vector container。
它知道它拥有它拥有的指针,因此会自动删除它们。
作为一个很好的副作用,当访问元素时,它返回对象的引用,而不是指针使代码看起来很好。
Foo *f = new Foo();
boost::ptr_vector<Foo> vect;
vect.push_back(f);
// do stuff
vect.erase(f);
答案 3 :(得分:2)
为了澄清指针未被删除的原因,请考虑
std::vector<char const*> strings;
strings.push_back("hello");
strings.push_back("world");
// .erase should not call delete, pointers are to literals
std::vector<int*> arrays;
strings.push_back(new int[10]);
strings.push_back(new int[20]);
// .erase should call delete[] instead of delete
std::vector<unsigned char*> raw;
strings.push_back(malloc(1000));
strings.push_back(malloc(2000));
// .erase should call free() instead of delete
一般来说,vector<T*>::erase
无法猜测你是如何处置T*
的。
答案 4 :(得分:1)
将指针指向标准容器绝对不是错误(然而,制作auto_ptr的容器是错误的)。是的,您需要明确删除以释放各个元素指向的内存,或者您可以使用其中一个提升smart pointers。
答案 5 :(得分:1)
vector删除它包含的数据。由于你的向量包含指针,它只删除指针,而不是它们可能指向或不指向的数据。
在C ++中,一个非常普遍的规则就是在分配内存时释放内存。该向量没有分配指针指向的任何内容,因此它不能释放它。
您可能不应该首先在向量中存储指针。 在许多情况下,你最好用这样的东西:
vector<Foo> vect;
vect.push_back(Foo());
// do stuff
vect.erase(f);
当然这假设Foo是可复制的,并且它的复制构造函数不是太昂贵,但它避免了内存泄漏,并且您不必记住删除Foo对象。另一种方法是使用智能指针(例如Boost的shared_ptr),但你可能根本不需要指针语义,在这种情况下,简单的解决方案是最好的。
答案 6 :(得分:1)
STL容器不会释放你的记忆。最好的建议是使用智能指针,因为知道std :: auto_ptr不适合容器内部。我建议使用boost :: shared_ptr,或者如果您的编译器供应商支持TR1扩展(很多),您可以使用std :: tr1 :: shared_ptr。
另请注意,向量甚至不会释放为指针保留的内部存储器。即使调用clear(),std :: vectors也不会缩小范围。如果你需要缩小矢量尺寸,你将不得不求助于创建另一个矢量并交换内容。