std :: vector如何分配对象?

时间:2012-04-26 20:45:40

标签: c++ vector std allocator

std::vector如何分配对象?它似乎只是使用std::allocator::allocate来创建一块内存,但从不调用std::allocate::construct。这是真的? std::vector是否只分配内存而从不将对象构造为内存分配?

如果没有默认构造函数怎么办?当对象上没有默认构造函数时,构造函数是如何调用的?如果有多个参数怎么办?

例如,使用此代码时,没有默认构造函数,std :: allocator允许它。

#include <vector>
using namespace std;

class A{
protected:
    int m;
public:
    explicit A(int a) : m(a) { }
};

int main(){
    vector<A> test;
    return 0;
}

2 个答案:

答案 0 :(得分:8)

自C ++ 11以来,这已经发生了相当大的变化。

在C ++ 03中,construct只能就地执行复制构建。

但请注意,std::vector特别是一个对象数组,但有一个不同的大小和容量。也就是说,在包含有用数据的数组部分的末尾之外可以有更多的元素。

这就是标准库的分配器在“构造”和“内存分配”之间存在分离的原因。 allocator同时执行这两项操作,但不能同时执行。这允许std::vector分配比它使用的内存更多的内存。添加新元素时,不一定要分配更多内存;它可以通过调用allocator::construct来使用它留下的备用内存。

另请注意,所有向std::vector 添加元素的C ++ 03函数都将元素作为参数。 push_backinsert,甚至是sized constructor takes as a value as an argument。是的,它是一个默认参数,但它仍然需要一个值作为元素。使用对分配器的construct方法的调用,将此元素复制到向量中。

在C ++ 11中,标准容器需要使用allocator_traits<>::construct函数。这是一个将其参数转发给实际构造的varadic函数。此特征函数将(默认情况下可以是专用的)调用allocator::construct方法(如果该调用格式正确)。如果不是,则会尝试展示new

这允许新的emplace功能起作用。

但是,标准库容器中包含的对象实际上是构造对象。即使没有调用分配器的construct方法。

答案 1 :(得分:0)

它依赖于实现,但是典型的实现使用std::allocator::allocate来分配内存块,然后使用placement new来构造,通过复制构造函数(或在C ++ 11中移动构造函数),实例

当元素被擦除时,即使未释放底层内存,也会直接调用它们的析构函数来销毁对象。