在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)
是POD,malloc
实际上等同于T
。
但是,我对此的理解是基于草案 C ++ 11标准,而不是最终标准。
问题:我的理解是否正确?如果explicit vector::vector(size_type count)
是POD,malloc
会提供未初始化的数组(类似于T
)吗?
答案 0 :(得分:21)
问题:我的理解是否正确?
explicit vector::vector(size_type count)
是否提供未初始化的数组 (如果malloc
是POD,则类似于T
)
没有。 C ++ 03和C ++ 11之间存在差异,但事实并非如此。区别在于,在C ++ 03中,vector<T>(N)
将默认构造一个T
,然后制作N
个副本以填充向量。
而在C ++ 11中,vector<T>(N)
将默认填充向量,构建T
N
次。对于POD类型,效果是相同的。实际上,我希望几乎所有类型的效果都是相同的。然而,对于类似unique_ptr
(仅移动类型)的东西,差异是至关重要的。 C ++ 03语义永远不会起作用,因为你无法复制仅移动类型。
所以:
vector<unique_ptr<int>> v(10);
创建一个10个null unique_ptrs的向量(它们不是彼此的副本)。
在极少数情况下,它会产生影响并且您需要可以通过以下方式轻松完成的C ++ 03行为:
vector<T> v(10, T());
答案 1 :(得分:7)
注意:值初始化发生在分配器中,因此如果您希望向量执行默认初始化而不是默认构造元素的值初始化,您可以执行以下操作:
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;