Updates:
The link above and the answers below didn't answer WHY this feature is not standardized. That is just what makes me wonder. Please consider the performance issue between std::vector<A> arr(8, 7);
and new A[8](7);
:
If we use std::vector<A> arr(8, 7);
it may (not must) be implemented as follows:
this->internal_buf = new A[8]; // Call default constructor A() 8 times!
for (auto i = 0; i < 8; ++i)
{
this->internal_buf[i] = A(7); // Call constructor A(7) 8 times AGAIN!!!
}
If C++ supports new A[8](7);
It can be implemented as follows:
A* arr = (A*)malloc(sizeof(A) * 8 + extra_size);
for (auto i = 0; i < 8; ++i)
{
new (&arr[i]) A(7); // Call constructor A(7) 8 times ONLY.
}
Compare the two methods, it is obvious that new A[8](7);
is FASTER than std::vector<A> arr(8, 7);
Besides, I also feel new A[8](7);
is more succinct and more expressive than std::vector<A> arr(8, 7);
Anyway, I think C++ should give programmers another alternative tool such as this feature. Because one of the C++ philosophies is "Give you as many tools as possible, but you don't have to pay for what you don't need."
The following is the original post:
struct A
{
int n;
A() : n() {}
A(int n) : n(n) {}
};
int main()
{
new A[8]; // OK
new A[8](); // OK
new A[8](7); // Error
}
Why can I not specify the constructor when newing an array?
Why does the C++ standard not support such a handy feature? What's the rationale?
Why does the C++ standard not support such a handy feature? What's the rationale?
Because there are better alternatives that can replace builtin arrays in (almost) all use cases (yes, even for passing to C-APIs): std::vector
for dynamic arrays (allocated with new
) and std::array
for stack-allocated ones.
With std::vector
, you could use std::vector<A> arr(8, 7)
(as WhozCraig commented) which creates a vector of 8 elements, initializing each of them with 7. Leaving out the second argument will use their default constructors (builtin types are initialized with 0
or false
).
Besides this and other convenience features (notably automatic resizing / push_back()
), the biggest advantage of std::vector
over creating arrays with new
is that it adheres to RAII, meaning that it will automatically delete[]
it's objects/memory as soon as it leaves scope -- no matter if by "falling off the function's end", a return
statement, break
, continue
, goto
or throwing an exception.
Vector is not implemented like this:
this->internal_buf = new A[8]; // Call default constructor A() 8 times!
for (auto i = 0; i < 8; ++i)
{
this->internal_buf[i] = A(7); // Call constructor A(7) 8 times AGAIN!!!
}
It is implemented roughly like:
typedef UninitializedBackingStoreForA B;
this->internal_buf = new B[8];
for (auto i = 0; i < 8; i++)
new (&B[i]) A(7);
That is it uses uninitialized storage and placement new to construct elements.
So your intuition is wrong, vector already has the performance you seek. The constructor is called once per element, and a default constructor is not required.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With