C++ 的向量如何分配内存

Posted

技术标签:

【中文标题】C++ 的向量如何分配内存【英文标题】:How C++'s Vector Allocate Memory 【发布时间】:2019-02-24 15:15:14 【问题描述】:

考虑我的代码,我有向量 P,它的类型是粒子。那么Particle里面也有向量x、v和xBest。

所以,它是向量中的向量。

struct Particle

    vector<double> x;
    vector<double> v;
    vector<double> xBest;
    double fitness;
    double pBest;
;

class Swarm

  public:
    vector<Particle> P;
    Swarm();
;

因为在声明类或结构时编译器不允许我为向量保留内存。像这样:

class Swarm

  public:
    vector<Particle> P(30);
    Swarm();
;

所以,我在构造函数中这样做:

Swarm::Swarm()

    P.reserve(30);
    for(size_t i = 0; i < 30; i++)
    
        P[i].x.reserve(10);
        P[i].v.reserve(10); 
        P[i].xBest.reserve(10);         
    

它的工作。

我对此非常好奇。由于 struct Particle 中向量的大小尚未初始化,因此 Particle 的大小是未知的。但是我可以在 struct Particle 中为 3 个向量保留内存之前为 30 个粒子保留内存!!

这怎么可能?

【问题讨论】:

小心,reserve 只是分配存储空间,它实际上并不创建对象;因此,每个iP[I] 都是UB。请改用resize vector&lt;Particle&gt; P(30); 在类声明中无效,但在 C++11 及更高版本中,您可以使用 vector&lt;Particle&gt; P30;vector&lt;Particle&gt; P = vector&lt;Particle&gt;(30); 代替。 Proof 【参考方案1】:

这是未定义的行为。当你 reserve 一个向量时,你不会创建对象,所以循环:

for(size_t i = 0; i < 30; i++)

    P[i].x.reserve(10);
    P[i].v.reserve(10); 
    P[i].xBest.reserve(10);         

在不存在的向量上调用reserve

您不能为不存在的向量预留容量。您需要先创建您的Particles。

【讨论】:

【参考方案2】:

在 C++ 中,每个对象所需的存储都是静态已知的,即在编译时。 C++ 中没有 VLA 之类的东西。 std::vector 不直接存储对象,它存储一个指向堆上数组的指针:

template <typename T>
class vector 
    // For illustration purposes only
    T *array;
    std::size_t size;
;

如您所见,向量的大小始终保持不变,无论它指向多少个元素,这就是您的示例(减去 cmets 中提到的 UB)有效的原因。

【讨论】:

以上是关于C++ 的向量如何分配内存的主要内容,如果未能解决你的问题,请参考以下文章

分配类型为自己的向量的内存 Class C++

c++ 内存分配向量的指针

我们可以控制向量数组(c++)中元素的内存分配吗?

为字符串向量预分配内存(C++ vector<string>)

在实时环境中使用 C++ 预分配内存

C ++中未初始化的内存分配