据我所知,对于两个向量声明:
//TYPE 1
std::vector<cls> vec; //cls is user defined datatype(A class)
向量的内存在堆栈上分配,向量中的内容内存在堆上分配。
以下声明也是如此(如果我错了,请纠正我):
//TYPE 2
std::vector<cls*> vec; //cls is user defined datatype(A class)
现在,当Type 1中的向量超出范围时,将为存储在其中的对象释放内存。
但是如果我在下面插入元素(假设我有正确的重载构造函数)然后向量超出范围,那么在类型2中会发生什么:
vec.push_back(new cls(5));
我明确尝试调用clear但是没有调用析构函数。是否会自动释放内存并调用析构函数。如果没有那么如何实现。
此外,如果我将vector声明为:
,则为向量分配内存以及内容std::vector<cls*> *vec = new std::vector<cls*>;
答案 0 :(得分:5)
这就是为什么我们有智能指针。
{
std::vector<std::unique_ptr<cls>> vec;
// C++14 will allow std::make_unique
vec.emplace_back(std::unique_ptr<cls>(new cls(5)));
}
当向量超出范围时,将调用unique_ptr
的析构函数并释放内存。
在您的情况下,使用原始指针,您必须delete
手动使用new
创建的任何内容:
// Something along the lines of this.
for (auto&& elem : vec) {
delete elem;
}
此外,如果我将vector声明为:
,则为向量分配内存以及内容
您正在使用new
分配向量,因此它将位于堆上。
答案 1 :(得分:4)
但是如果我插入如下的元素,那么在类型2中会发生什么(假设如此) 我有适当的重载构造函数)然后向量熄灭 范围:
内存将泄漏 - 您需要单独迭代矢量和delete
每个元素。
答案 2 :(得分:3)
如果在向量中存储指向对象的指针,则需要在销毁向量之前删除元素(或者有内存泄漏,但这不是一件好事)。但你不应该使用“原始”指针。如果您使用unique_ptr<cls>
代替*cls
,问题就解决了。
所以而不是:
vec.push_back(new cls(5))
使用
vec.push_back(unique_ptr(new cls(5)))
或
vec.push_back(make_unique<cls>(5))
你不必担心找到一些地方来迭代矢量并删除内容。
new vector<...>
“正确”的情况非常少。如果你这样做,想一想是否真的有必要。
答案 3 :(得分:2)
对于此类型,您可以通过执行vec.push_back (new cls)
//TYPE 2
vector<cls*> vec; //cls is user defined datatype(A class)
但是向量将清除指针变量的内存,但不会清除它们指向的实例,你必须在vec内的每个cls *上运行delete。否则你有内存泄漏。
答案 4 :(得分:2)
std::vector
如果动态分配,delete
将不会std::shared_ptr
存储在其中的对象。你必须自己这样做。最好完全避免使用原始内存 - 通常您希望将指针包装在std::unique_ptr
或vector
中。它们都会自动为你释放内存。
请勿使用new
创建{{1}}。
答案 5 :(得分:2)
向量的内存不一定在堆栈上分配。正如您在最后一个片段中所示,可以从堆中分配向量的内存。
当向量超出堆栈的范围时,或者如果在堆上使用new分配向量,则使用delete销毁向量,它将自动销毁其所有元素。但是,常规指针没有析构函数,并且不会对它们死时指向的对象做任何特殊操作。因此,虽然清除指针向量会破坏指针,但它们指向的对象不会被破坏。
有两种解决方案。在清除向量之前,遍历向量中的每个指针并在其上调用delete。更好的解决方案是使用智能指针,例如unique_ptr。当unique_ptr被销毁时,它指向的对象将被自动删除。
所以用
vector<unique_ptr<cls>>
,你可以像你一样推回新的cls,当矢量被破坏时,你通过unique_ptr插入到矢量中的所有cls对象也会被破坏。
答案 6 :(得分:2)
保持指针的向量不对指针指向的内存负责。 当向量超出范围时,它将释放它对指针的内存,而不是这些指针所指向的内存。
管理这段记忆仍然是你的责任。这就是为什么你应该使用智能指针std::unique_ptr
或std::shared_ptr
来避免内存泄漏(如果忘记手动删除,可能会发生这种情况)。
此外,如果我将vector声明为:
,则为向量分配内存以及内容
vector<cls*> *vec = new vector<cls*>;
向量在堆上,内容就在它的任何地方(例如,如果你按new
分配它,它可能在堆上;如果你这样做,它可能在堆栈上:cls myCls; cls* myPointerToCls = &cls;
,然后vec.push_back(myPointerToCls);
)
答案 7 :(得分:1)
好的答案很多,
您需要迭代矢量并单独删除每个元素
我将展示一个小例子:
class cls
{
public:
cls(int x) :_a(x) {}
~cls() {cout<<"I'm Destroyed"<<endl ;}
private:
int _a;
};
int main()
{
vector<cls*> vec ;
for(auto i=1;i<=10;i++)
vec.push_back(new cls(i));
for (auto it = vec.begin(); it != vec.end(); ++it)
delete *it;
{
vector<cls*> vec2 ;
vec2.push_back(new cls(10));
}
//Here vec2 out of scope
}
输出: 我被摧毁了&lt;只有10次&gt;