【问题标题】:Allocating a vector vs. a pointer to a vector [duplicate]分配向量与指向向量的指针[重复]
【发布时间】:2014-03-13 04:15:15
【问题描述】:

假设我有两套代码,

std::vector<float>v1;

std::vector<float> *pV2 = new std::vector<float>(10);

除了你将有一个更大的内存块分配给向量的指针之外,两者之间有什么区别?一个比另一个有优势吗?

在我看来,分配指针似乎更麻烦,因为您必须稍后处理释放它。

【问题讨论】:

标签: c++ pointers vector


【解决方案1】:

除了你将使用指向向量的指针分配更大的内存块之外,两者之间有什么区别?

  1. '将分配更大的内存块'
    这不一定是真的! std::vector 可能会为内部管理的数据数组选择一个比10 大得多的默认初始大小。
  2. '两者有什么区别'
    主要区别在于第一个分配在本地范围堆栈上, 第二个(通常)进入堆。 注意:内部管理的数据数组无论如何都会进入堆!!

当您确实必须使用从堆分配的std::vector&lt;float&gt;* 指针时,为了确保正确的内存管理,我建议使用 智能指针,例如:

std::unique_ptr<std::vector<float> > pV2(new std::vector<float>(10));

更多详情请查看&lt;memory&gt;的文档。

【讨论】:

    【解决方案2】:

    其中一个关键区别是范围。在您的第一个示例中,向量可能是类的成员,或者是函数的本地成员。如果它是一个类成员,它会在包含对象被销毁时被销毁。如果它是函数本地的,它将在函数结束时被销毁。该对象绝对不能在此之外存在,因此如果您尝试将其地址传递给程序的另一部分,则必须非常小心。

    当您手动在堆上分配某些东西时,它会一直存在,只要您愿意。您可以完全控制释放,这意味着您可以在一个对象/函数中创建它,并在需要时在另一个对象/函数中使用或删除它。

    在各种情况下,能够延迟对象的实例化直到它真正需要它也是非常有用的。例如,根据用户输入,它可能需要不同的构造参数,或者您可能希望利用多态性(即在运行时决定要实例化哪个子类)。

    某些情况下的另一个关键区别是可用内存。如果您在函数本地创建对象,它将驻留在堆栈中。堆栈上的可用空间比堆上少得多,因此在使用特别大的对象时可能会遇到困难(尽管向量不会发生这种情况,因为它无论如何都是在堆上分配的)。

    值得注意的是,对象实际使用的内存量是一样的,不管是在栈上还是在堆上。唯一的区别是,如果你在堆上手动分配一些东西,那么你也会有一个指向它的指针。不过,这只是额外的 4 或 8 个字节,在大多数情况下可以忽略不计。

    【讨论】:

    • '值得注意的是,对象的实际内存使用量是相同的' 不,不是!它在堆栈或堆上的区别是 sizeof(std::vector&lt;float&gt;) - sizeof(std::vector&lt;float&gt;*) ...
    • @πάνταῥεῖ:你能详细说明你的意思吗?为什么大小会不一样?
    • 将另一个std::vector&lt;float&gt; 对象添加到堆中(OP 的第二种情况),需要从那里额外的sizeof(std::vector&lt;float&gt;)(最终对齐)字节,不是吗??
    • 我不这么认为。无论分配在哪里,都应该是完全相同的大小。如果不是,则数组遍历和指针运算会有所不同,具体取决于数据是在堆栈上还是在堆上。
    • 我想你误解了:对于std::vector&lt;&gt; 对象内部管理的数据,没有区别(正如我在回答中也提到的)。但是对于在堆或堆栈上管理的std::vector&lt;&gt; 对象本身,有(至少sizeof(std::vector&lt;float&gt; - sizeof(std::vector&lt;float*&gt;)!这有点吹毛求疵,但在递归调用函数并使用堆栈分配的向量时可能很重要。对于一个进程的整体内存消耗来说,根本没有太大的区别。
    猜你喜欢
    • 2011-08-04
    • 2014-02-23
    • 1970-01-01
    • 2013-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-08-28
    • 1970-01-01
    相关资源
    最近更新 更多