STL中的容器对象(如vector)是在堆上创建的,那么它们如何被销毁呢?
编辑
如果容器持有指针,则如何销毁这些指针对象?
STL中的容器对象(如vector)是在堆上创建的,那么它们如何被销毁呢?
编辑
如果容器持有指针,则如何销毁这些指针对象?
STL容器中存储指针类型的数据时,仅会清理指针所占用的空间,而不会清理指针所指向的数据。如果您希望容器可以清理指针所指向的数据,则需要使用某种智能指针实现:
{
std::vector<SomeClass*> v1;
v1.push_back(new SomeClass());
std::vector<boost::shared_ptr<SomeClass> > v2;
boost::shared_ptr<SomeClass> obj(new SomeClass);
v2.push_back(obj);
}
当作用域结束时,两个向量将释放其内部数组。v1将泄漏创建的SomeClass,因为只有指向它的指针在数组中。v2不会泄露任何数据。
vector<T*>
,在删除向量之前,你的代码需要删除这些指针:否则,该内存将被泄漏。typedef vector<T*> vt;
⋮
vt *vt1 = new vt, *vt2 = new vt;
T* t = new T;
vt1.push_back(t);
vt2.push_back(t);
⋮
delete vt1;
delete vt1;
)显然不应该删除指针所指向的内容,毕竟它也在vt2中。所以它并没有被删除,vt2
同样不会被删除。这有点名不副实。就像大多数STL容器一样,向量由两个逻辑部分组成。
虽然可配置,但#2几乎总是存在于堆上。但是#1可以存在于堆栈或堆上,这取决于它是如何分配的。例如:
void foo() {
vector<int> v;
v.push_back(42);
}
for (ContainerType::iterator it(container.begin()); it != container.end(); ++it)
{
delete (*it);
}
std::vector<int> vec(10);
就像任何其他堆栈变量一样,它只存在于定义它的函数范围内,并且不需要手动删除。STL容器的析构函数将调用容器中所有元素的析构函数。
在容器中保留指针是一个棘手的问题。由于指针没有析构函数,因此我会说您永远不想将裸指针放入STL容器中。以异常安全的方式执行此操作将非常困难,您必须在代码中散布try {} finally {}块,以确保所包含的指针始终被释放。
那么,除了裸指针之外,您应该把什么放入容器中?+1 jmucchiello提出boost::shared_ptr。boost::shared_ptr在STL容器中使用是安全的(不像std::auto_ptr)。它使用简单的引用计数机制,并且适用于不包含循环的数据结构。
如果数据结构包含循环,那么需要什么呢?在这种情况下,您可能希望升级到垃圾回收,这实际上意味着使用不同的语言,如Java。但这是另一个讨论。
回答你的第一个问题:
STL类没有什么特别之处(我希望如此)。它们的功能与其他模板类完全相同。因此,如果在堆上分配了它们,它们不会自动销毁,因为C++对它们没有垃圾回收(除非您使用一些复杂的autoptr技巧告诉它如何处理)。如果您在堆栈上分配它(而不是使用new),它很可能会被C++自动管理。
至于你的第二个问题,这里有一个非常简单的ArrayOfTen类来演示C++中典型内存管理的基础知识:
/* Holds ten Objects. */
class ArrayOfTen {
public:
ArrayOfTen() {
m_data = new Object[10];
}
~ArrayOfTen() {
delete[] m_data;
}
Object &operator[](int index) {
/* TODO Range checking */
return m_data[index];
}
private:
Object *m_data;
ArrayOfTen &operator=(const ArrayOfTen &) { }
};
ArrayOfTen myArray;
myArray[0] = Object("hello world"); // bleh
基本上,ArrayOfTen类在堆上保留了十个对象元素的内部数组。当在构造函数中调用new[]时,在堆上分配了十个对象的空间,并构造了十个对象。同样,当在析构函数中调用delete[]时,十个对象被析构,然后先前分配的内存被释放。
对于大多数(所有?)STL类型,调整大小是在幕后完成的,以确保有足够的内存来容纳您的元素。上述类仅支持包含十个对象的数组。它基本上是Object[10]的非常限制性的typedef。