11

据我所知,对于这两个向量声明:

//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)

现在,当类型 1 中的向量超出范围时,将为存储在其中的对象释放内存。

但是,如果我插入如下元素(假设我有适当的重载构造函数)然后向量超出范围,则类型 2 会发生什么:

vec.push_back(new cls(5));

我明确尝试调用 clear 但未调用析构函数。是否会自动释放内存并调用析构函数。如果没有,那么如何实现。

此外,如果我将向量声明为:

std::vector<cls*> *vec = new std::vector<cls*>;
4

8 回答 8

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将调用 s 的析构函数并释放内存。

在您的情况下,使用原始指针,您必须手动delete创建任何内容:new

// Something along the lines of this.
for (auto&& elem : vec) {
    delete elem;
}

此外,如果我将向量声明为:

你用 分配向量new,所以它会在堆上。

于 2013-07-29T13:47:16.220 回答
4

但是,如果我插入如下元素(假设我有适当的重载构造函数)然后向量超出范围,则类型 2 会发生什么:

内存会泄漏——你需要单独迭代你的向量和delete每个元素。

于 2013-07-29T13:46:50.173 回答
3

如果将指向对象的指针存储在向量中,则需要在销毁向量之前删除元素(或有内存泄漏,但这不是一件好事)。但是你不应该使用“原始”指针。如果您使用 exampleunique_ptr<cls>而不是*cls,问题就解决了。

所以而不是:

vec.push_back(new cls(5))

采用

vec.push_back(unique_ptr(new cls(5)))

或者

vec.push_back(make_unique<cls>(5))

而且您不必担心找到一些地方来迭代向量并删除内容。

很少有 anew vector<...>是“正确”的情况。如果您这样做,请考虑是否真的有必要。

于 2013-07-29T13:47:21.133 回答
2

不适合这种类型,你可以推回一个新的 cls 字节做vec.push_back (new cls)

//TYPE 2
vector<cls*> vec;    //cls is user defined datatype(A class)

但是向量将清除指针变量的内存,但不会清除它们指向的实例,您必须在 vec 内的每个 cls* 上运行 delete。否则你有内存泄漏。

于 2013-07-29T13:47:23.277 回答
2

如果对象是动态分配的,Astd::vector将不会存储其中的对象。delete你必须自己这样做。最好完全避免使用原始内存——通常您希望将指针包装在其中std::shared_ptrstd::unique_ptr代替。它们都会自动为您释放内存。

不要vector使用new.

于 2013-07-29T13:47:23.383 回答
2

向量的内存不一定在堆栈上分配。正如您在上一个片段中显示的那样,可以从堆中分配 vector 的内存。

当向量超出堆栈范围时,或者当向量在堆上使用 new 分配时使用 delete 销毁,它将自动销毁其所有元素。但是,常规指针没有析构函数,并且在它们死亡时不会对它们指向的对象做任何特殊的事情。因此,尽管清除指针向量会破坏指针,但它们指向的对象不会被破坏。

有两种解决方案。在清除向量之前,遍历向量中的每个指针并对其调用 delete。更好的解决方案是使用智能指针,例如 unique_ptr。当一个 unique_ptr 被销毁时,它指向的对象被自动删除。

所以用一个

vector<unique_ptr<cls>>

,您可以像这样做一样推回新的 cls,并且当向量被销毁时,您通过 unique_ptr 插入向量中的所有 cls 对象也将被销毁。

于 2013-07-29T13:47:54.073 回答
2

持有指针的向量不负责指针指向的内存。当向量超出范围时,它将释放它为指针所拥有的内存,而不是这些指针指向的内存。

管理此内存仍然是您的责任。这就是为什么你应该使用智能指针std::unique_ptr,或者std::shared_ptr避免内存泄漏(如果你忘记手动删除可能会发生这种情况)。

此外,如果我将向量声明为:

vector<cls*> *vec = new vector<cls*>;

向量在堆上,内容在它所在的任何地方(例如,如果你分配它,它可能在堆上new,或者如果你分配它,它可能在堆栈上 : cls myCls; cls* myPointerToCls = &cls;,然后vec.push_back(myPointerToCls);

于 2013-07-29T13:48:35.190 回答
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
}

输出:我被摧毁了<只有10次>

于 2013-07-29T13:58:45.287 回答