Initialized Objects in C++11 and std::vector constructor
In C++ there are few compelling reasons to use a C array over std::vector
. One of those few compelling reasons, at least with C++03, was the fact that it is impossible to use a vector to allocate an uninitialized array of objects. The "fill" constructor for std::vector
is:
vector(size_type count, const T& value = T())
Meaning that...
int* array = new array[1000000];
is likely to be much more efficient than:
std::vector<int> v(1000000);
...since the vector constructor will have to zero-initialize the array of integers. Thus, when working with a vector of PODs, there is no real equivalent to malloc
; the best you can get is an equivalent to calloc
.
C++11 seems to have changed this, with the concept of "value-initialization." In C++11, std::vector
has a new constructor which takes a single size_type
value, with no default argument. This "value-initializes" all elements in the vector. The C++11 standard distinguishes between "value-initialization" and "zero-initialization."
My understanding is that "value-initialization" is equivalent to calling the default constructor on T
. If T
is a POD type like int
, then the default constructor simply creates an uninitialized integer. Thus, in C++11, explicit vector::vector(size_type count)
is truly equivalent to malloc
if T
is a POD.
However, my understanding of this is based on the draft C++11 standard, rather than the final standard.
Question : Is my understanding correct here? Does explicit vector::vector(size_type count)
provide an uninitialized array (similar to malloc
) if T
is a POD?
Question : Is my understanding correct here? Does explicit vector::vector(size_type count)
provide an uninitialized array (similar to malloc
) if T
is a POD?
No. There is a difference here between C++03 and C++11, but that isn't it. The difference is that in C++03, vector<T>(N)
would default construct a T
, and then make N
copies of it to populate the vector.
Whereas in C++11, vector<T>(N)
will populate the vector by default constructing T
N
times. For POD types the effect is identical. Indeed, I would expect that for almost all types the effect is identical. However for something like a unique_ptr
(a move-only type), the difference is critical. The C++03 semantics would never work since you can not make a copy of a move-only type.
So:
vector<unique_ptr<int>> v(10);
creates a vector of 10 null unique_ptrs (which are not copies of each other).
In the rare case that it makes a difference and you need the C++03 behavior that can easily be accomplished with:
vector<T> v(10, T());
注意:值初始化发生在分配器中,所以如果你想要一个向量执行默认初始化而不是默认构造元素的值初始化,你可以做如下的事情:
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;
链接地址: http://www.djcxy.com/p/67786.html