15

在 C++ 中,使用 C 数组而不是std::vector. 至少在 C++03 中,为数不多的令人信服的原因之一是不可能使用向量来分配未初始化的对象数组。“填充”构造函数std::vector是:

vector(size_type count, const T& value = T())

意思是...

int* array = new array[1000000];

可能比:

std::vector<int> v(1000000);

...因为向量构造函数必须对整数数组进行零初始化。因此,当使用 POD 向量时,没有真正的等价于malloc; 你能得到的最好的就是calloc.

C++11 似乎用“值初始化”的概念改变了这一点。在 C++11 中,std::vector有一个新的构造函数,它采用单个size_type值,没有默认参数。这“值初始化”了向量中的所有元素。C++11 标准区分“值初始化”和“零初始化”。

我的理解是“值初始化”相当于在T. 如果T是类似的 POD 类型int,则默认构造函数只是创建一个未初始化的整数。因此,在 C++11 中,explicit vector::vector(size_type count)真正等同于mallocif Tis a POD。

但是,我对此的理解是基于草案C++11 标准,而不是最终标准。

问题:我的理解在这里正确吗?如果是 POD ,是否explicit vector::vector(size_type count)提供未初始化的数组(类似于)?mallocT

4

2 回答 2

22

问题:我的理解在这里正确吗?如果是 POD ,是否explicit vector::vector(size_type count)提供未初始化的数组(类似于)?mallocT

不,C++03 和 C++11 之间是有区别的,但事实并非如此。不同之处在于,在 C++03 中,vector<T>(N)将默认构造 a T,然后N对其进行复制以填充向量。

而在 C++11 中,默认构造时间vector<T>(N)将填充向量。T N对于 POD 类型,效果是相同的。事实上,我希望几乎所有类型的效果都是相同的。然而,对于像unique_ptr(只移动类型)这样的东西,差异是至关重要的。C++03 语义永远不会起作用,因为您无法复制仅移动类型。

所以:

vector<unique_ptr<int>> v(10);

创建一个包含 10 个空 unique_ptrs 的向量(它们不是彼此的副本)。

在极少数情况下它会有所作为,您需要可以通过以下方式轻松完成的 C++03 行为:

vector<T> v(10, T());
于 2013-02-26T19:58:43.943 回答
9

Note: the value-initialization happens in the allocator, so if you want a vector to do default initialization instead of value initialization for default constructed elements, you can do something like:

template<typename T>
struct DefaultInitAllocator {
    template<typename U>
    void construct(U* p)
    { ::new (static_cast<void*>(p)) U; }

    template<typename U, typename... Args>
    void construct(U* p, Args&&... args)
    { ::new (static_cast<void*>(p)) U(std::forward<Args>(args)...); }

    // ... rest of the allocator interface
};

// ...
typedef std::vector<int, DefaultInitAllocator<int>> DefaultInitVectorInt;
于 2013-02-27T18:36:19.340 回答