简体   繁体   English

std :: vector如何分配对象?

[英]How does std::vector allocate objects?

How does std::vector allocate objects? std::vector如何分配对象? It would seem as if it just uses std::allocator::allocate to create a block of memory, but then never calls std::allocate::construct . 看起来好像它只是使用std::allocator::allocate来创建一个内存块,但是从不调用std::allocate::construct Is this true? 这是真的? Does std::vector only allocate memory and never construct the objects as memory allocation? std::vector是否只分配内存而从不构造对象作为内存分配?

What if there is no default constructor? 如果没有默认构造函数怎么办? How is the constructor called when there is no default constructor on the object? 当对象上没有默认构造函数时,构造函数是如何调用的? What if there is more than one parameter? 如果有多个参数怎么办?

For example, with this code there is no default constructor and std::allocator allows it. 例如,使用此代码没有默认构造函数,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;
}

This has rather changed since C++11. 自C ++ 11以来,这已经发生了很大变化。

In C++03, construct could only perform copy-construction in-place. 在C ++ 03中, construct只能就地执行复制构造。

However, note that std::vector in particular is an array of objects, but there is a distinct size and capacity. 但是,请注意std::vector特别是一个对象数组,但是有一个不同的大小和容量。 That is, there can be more empty elements beyond the end of the part of the array that contains useful data. 也就是说,在包含有用数据的数组部分的末尾之外可以有更多的元素。

That is why the standard library's allocator has a separation between "construction" and "memory allocation." 这就是标准库的分配器在“构造”和“内存分配”之间存在分离的原因。 The allocator does do both, but not at the same time . allocator确实做到了这allocator ,但不能同时做到。 This allows std::vector to allocate more memory than it uses. 这允许std::vector分配比它使用的内存更多的内存。 When you add new elements, it doesn't necessarily have to allocate more memory; 添加新元素时,不一定要分配更多内存; it can just use the spare memory it has left over via a call to allocator::construct . 它可以通过调用allocator::construct来使用它留下的备用内存。

Also, note that all of the C++03 functions that add elements to std::vector take an element as a parameter. 此外,请注意所有这些添加元素添加到C ++ 03功能std::vector 取的元素作为参数。 push_back , insert , even the sized constructor takes as a value as an argument . push_backinsert ,甚至是大小的构造函数都将值作为参数 Yes, it's a default parameter, but it still takes a value as an element. 是的,它是一个默认参数,但它仍然需要一个值作为元素。 This element is copied into the vector, using a call to the allocator's construct method which takes a copy. 使用对分配器的construct方法的调用将该元素复制到向量中,该construct方法获取副本。

In C++11, standard containers are required to use the allocator_traits<>::construct function. 在C ++ 11中,标准容器需要使用allocator_traits<>::construct函数。 This is a varadic function that forwards its parameters to the actual construct. 这是一个将其参数转发给实际构造的varadic函数。 This traits function will (by default. It can be specialized) call the allocator::construct method if that call is well-formed. 这个traits函数将(默认情况下可以是专用的)调用allocator::construct方法,如果该调用格式正确的话。 If it isn't, it will try placement new . 如果不是,它将尝试放置new

This allows for the new emplace functions to work. 这允许新的emplace功能起作用。

But yes, the objects contained in standard library containers are in fact constructed objects. 但是,标准库容器中包含的对象实际上是构造对象。 Even if the allocator's construct method is not called. 即使没有调用allocator的construct方法。

It's implementation dependent, but a typical implementation uses std::allocator::allocate to allocate the block of memory, and then uses the placement new to construct, via the copy constructor (or move constructor in C++11), the instances. 它依赖于实现,但是典型的实现使用std::allocator::allocate来分配内存块,然后使用placement new来构造,通过复制构造函数(或在C ++ 11中移动构造函数)来构造实例。

When elements are erased, their destructors are directly invoked to destroy the objects, even if the underlying memory isn't released. 删除元素时,即使未释放底层内存,也会直接调用它们的析构函数来销毁对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM