C++ std::向量破坏和意外内存泄漏
考虑以下示例:C++ std::向量破坏和意外内存泄漏,c++,memory-leaks,vector,C++,Memory Leaks,Vector,考虑以下示例: #include <vector> class Foo { std::vector<int*> v; public: Foo() { this->v.push_back(new int(23)); this->v.push_back(new int(24)); this->v.push_back(new int(25)); } ~Foo() { }
#include <vector>
class Foo {
std::vector<int*> v;
public:
Foo() {
this->v.push_back(new int(23));
this->v.push_back(new int(24));
this->v.push_back(new int(25));
}
~Foo() {
}
};
int main() {
Foo f;
return 0;
}
int a = 5;
int* i = &a;
if (true)
{
int* j = i;
} //j goes out of scope, should *i and a be deleted? no.
我错过了什么
现在应该调用向量v
的每个元素的析构函数
是:向量中存储的int*
对象被销毁(这实际上是一个否定操作)。容器中指针指向的对象不会被销毁
考虑以下同样有效的计划:
{
int x;
std::vector<int*> v;
v.push_back(&x);
} // x cannot be delete'd because it isn't dynamically allocated.
{
int x;
std::向量v;
v、 向后推(&x);
}//无法删除x,因为它不是动态分配的。
您应该使用智能指针,如
std::unique_ptr
或shared_ptr
,这样就不必担心内存管理(不要使用std::auto_ptr
;它与标准库容器不兼容,因为它实际上不可复制)。如果不使用智能指针,则需要自己销毁动态对象;正确执行此操作相当困难。向量的每个元素都是一个int*
。当int*
被销毁时,该语言不会自动对其调用delete
。换句话说,被销毁的是指针,而不是指针对象。std::vector
确实在销毁时调用了T
的析构函数。这里的T
是int*
。int*
的析构函数不执行任何操作。int*
本身的存储被释放,但它们指向的int
s未被释放
考虑:
int main() {
int *x = new int(23);
return 0;
}
这表现出同样的问题;当x
超出范围时,它的析构函数确实被调用,指针x
的存储被释放,但由于指针的析构函数是no op,指向的int
不会被释放
更重要的是,vector
不知道int
s是如何分配的。它们可以由new int
分配,但也可以指向用new int[200]
分配的数组中的元素,或者指向malloc
'd数据,或者指向mmap
'd缓冲区,或者指向结构元素,或者两个向量可能指向相同的int
s。。。等等。vector
不够聪明,无法预测你想用它们做什么,因此它将它们放在一边(另外,给vector
逻辑删除指向元素会破坏非指针元素的向量,例如std::vector
,因为你不能删除一个int
!)
您需要使用std::vector
,或者将智能指针与之结合使用,例如std::vector
。请注意,使用智能指针可能会增加开销;使用C++0x,您应该能够将std::vector
与std::move
结合使用,以避免这种开销。Boost还可以像您期望的那样释放指向元素。因为您使用的是new
关键字,整数是在堆上而不是堆栈上分配的。换句话说,它们是动态分配的。换言之,你需要清理后,它
指针类型的“析构函数”就是简单地删除该指针。它不接触指针存储的内存地址处的数据。考虑下面的例子:
#include <vector>
class Foo {
std::vector<int*> v;
public:
Foo() {
this->v.push_back(new int(23));
this->v.push_back(new int(24));
this->v.push_back(new int(25));
}
~Foo() {
}
};
int main() {
Foo f;
return 0;
}
int a = 5;
int* i = &a;
if (true)
{
int* j = i;
} //j goes out of scope, should *i and a be deleted? no.
因此,您需要在析构函数中执行此操作:
std::vector<int*>::iterator iter;
for (iter = v.begin(); iter != v.end(); iter++)
{
delete *iter;
}
std::vector::iter;
对于(iter=v.begin();iter!=v.end();iter++)
{
删除*国际热核实验堆;
}
注意,unique\u ptr
只能在STL容器中使用,如果您使用C++0x,并且在插入项目时使用std::move
。是的,这回答了我的问题。int*指向的内存不会被释放,尽管指针本身会被释放。非常感谢。可能重复的