为什么我需要手动删除向量中动态创建的项目?当向量被删除时,为什么它们不会被删除或调用其析构函数?
通常是这样的,但为什么需要?
vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it)
{
delete *it;
}
为什么我需要手动删除向量中动态创建的项目?当向量被删除时,为什么它们不会被删除或调用其析构函数?
通常是这样的,但为什么需要?
vector<int*> v;
for (vector<int*>::iterator it = v.begin(); it != v.end(); ++it)
{
delete *it;
}
首先,您将原始指针存储在向量中。这些指针只是指针。他们可以指向任何地方。它们可以指向本地对象,这些对象不能被delete
. 即使它们指向动态创建的对象,也不一定意味着用户希望它们与向量一起死亡。向量应该如何知道这一切?
这是对象所有权的问题。拥有该对象的人应对其正确及时的删除负责。普通的原始指针不表示所有权。这就是为什么vector无法对对象是否需要删除做出任何假设。如果您想告诉向量它拥有其动态对象,请使用相应的智能指针。
其次,请注意,您的删除技术在一般情况下不一定安全。一些标准容器假定您存储在其中的数据始终有效。当您delete
对每个向量元素执行此操作时,向量中的数据将变为“无效”(指针变得不确定)。这对向量来说是可以的。但是在一个“更智能”的容器中做这样的事情,比如std::map
或std::unordered_set
例如,可能而且将会导致问题。即使您随后立即销毁容器本身,容器的销毁算法也很可能需要分析(比较、散列等)各个元素的值。而你只是用你的周期杀死了他们。
智能指针自然地解决了这个问题。但是,如果您必须使用delete
存储在标准容器中的原始指针的手册,则更好的步骤顺序将是
i
并将其存储在指针中p
i
从容器中擦除元素delete p
最后你会得到一个空容器和delete
d 数据。同样,您的方法适用于简单的序列,例如std::vector
or std::list
,但不要对有序或散列的序列执行此操作。
因为语言无法知道您完成后是否需要它们保持活力。如果您插入一些指向堆栈对象的指针或类似的东西怎么办?繁荣。
然而,这可以通过使用智能指针来解决,智能指针将实施适当的策略来自动销毁。unique_ptr
并且shared_ptr
是最常见和最有用的。
不调用析构函数是因为指针不拥有它所指向的对象。
在 C++11 中,astd::unique_ptr<T>
确实拥有它所指向的对象。在这种情况下,释放指针时会调用析构函数,这可能是您想要的行为。(如果您没有 C++11 编译器,但拥有相当新的 C++11 之前的编译器,unique_ptr
则仍可作为 TR1 的一部分使用。)
的实现vector
只是为了删除它的内存。指针没有解构器。而在 C++ 中,没有垃圾收集或逻辑可以看到它是指针并递归删除它。
如果你想参加下一次 ISO 会议并提出这个建议,请做我的客人,但对我来说,我只是把它放在一个inline
函数中:
template<class T>
public static inline void deleteVectorPointer(std::vector<T*> v)
{
for (vector<T*>::iterator i = v.begin(); i != v.end(); i++)
{
delete *i;
}
}