7

如果我有以下代码,

Foo *f = new Foo();
vector<Foo*> vect;
vect.push_back(f);
// do stuff
vect.erase(f);

我是否造成了内存泄漏?我猜是这样,但擦除这个词给人的感觉是它正在删除它。

写到这里,我想知道将指针放在 STL 向量中是否是一个错误。你怎么看?

4

7 回答 7

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>更快的,因为它不允许复制。在 c++0x 中使用std::unique_ptr容器类似于ptr_containerboost 中的库。

于 2008-11-11T16:27:44.813 回答
4

另一种选择是使用 Boost Pointer Containers。它们旨在完全按照您的意愿行事。

于 2008-11-11T16:35:08.043 回答
2

或者有 boost::ptr_vector容器

它知道它持有它拥有的指针,因此会自动删除它们。

作为一个很好的副作用,当访问元素时,它返回对对象的引用而不是指针,以使代码看起来不错。

Foo *f = new Foo();
boost::ptr_vector<Foo>  vect;
vect.push_back(f);
// do stuff
vect.erase(f);
于 2008-11-11T16:37:32.203 回答
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*.

于 2008-11-12T10:04:23.823 回答
1

将指针指向标准容器绝对不是错误(但是,创建 auto_ptr 的容器是错误的)。是的,您确实需要显式删除以释放各个元素指向的内存,或者您可以使用 boost smart pointers之一。

于 2008-11-11T16:34:14.787 回答
1

vector 删除它包含的数据。由于您的向量包含指针,它只删除指针,而不是它们可能指向或可能不指向的数据。

在 C++ 中,内存在分配的地方释放是一个非常普遍的规则。向量没有分配你的指针指向的任何东西,所以它不能释放它。

您可能首先不应该将指针存储在向量中。在许多情况下,您最好使用以下方法:

vector<Foo> vect;
vect.push_back(Foo());
// do stuff
vect.erase(f);

当然这假设 Foo 是可复制的,并且它的复制构造函数不是太昂贵,但是它避免了内存泄漏,并且您不必记住删除 Foo 对象。另一种方法是使用智能指针(例如 Boost 的 shared_ptr),但您可能根本不需要指针语义,在这种情况下,简单的解决方案是最好的解决方案。

于 2008-11-11T17:18:40.983 回答
1

STL 容器不会释放您的内存。最好的建议是使用智能指针,因为它知道 std::auto_ptr 不适合容器。我会推荐 boost::shared_ptr,或者如果您的编译器供应商支持 TR1 扩展(很多都支持),您可以使用 std::tr1::shared_ptr。

另请注意,向量甚至不会释放为指针保留的内部存储器。即使调用 clear(),std::vectors 也不会缩小大小。如果您需要缩小矢量,您将不得不求助于创建另一个矢量并交换内容。

于 2008-11-11T19:40:49.400 回答