更新
上面的链接和下面的答案没有回答为什么此功能未标准化。这才是让我惊讶的原因。请考虑std::vector<A> arr(8, 7);
和new A[8](7);
之间的效果问题:
如果我们使用std::vector<A> arr(8, 7);
,可以(不一定)按如下方式实施:
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!!!
}
如果C ++支持new A[8](7);
它可以按如下方式实现:
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.
}
比较这两种方法,显然new A[8](7);
更快而不是std::vector<A> arr(8, 7);
此外,我也觉得new A[8](7);
比std::vector<A> arr(8, 7);
无论如何,我认为C ++应该为程序员提供另一种替代工具,例如此功能。因为C ++哲学之一是“尽可能多地为你提供工具,但你不必为你不需要的东西买单。”
以下是原帖:
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
}
为什么在新建数组时不能指定构造函数?
为什么C ++标准不支持这样一个方便的功能? 理由是什么?
答案 0 :(得分:3)
为什么C ++标准不支持这样一个方便的功能?理由是什么?
因为有更好的替代品可以替代(几乎)所有用例中的内置数组(是的,甚至是传递给C-API):std::vector
用于动态数组(用new
分配)和std::array
用于堆栈分配的。
使用std::vector
,你可以使用std::vector<A> arr(8, 7)
(如WhozCraig评论的那样)创建一个包含8个元素的向量,用7初始化每个元素。省略第二个参数将使用它们的默认构造函数(内置使用0
或false
)初始化类型。
除了这个和其他便利功能(特别是自动调整大小/ push_back()
)之外,std::vector
优于使用new
创建数组的最大优势是它遵守RAII,这意味着它一旦离开范围就会自动delete[]
它的对象/内存 - 无论是“从函数的末尾掉下来”,return
语句,break
,{{ 1}},continue
或抛出异常。
答案 1 :(得分:3)
Vector未实现如下:
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!!!
}
它的实现大致如下:
typedef UninitializedBackingStoreForA B;
this->internal_buf = new B[8];
for (auto i = 0; i < 8; i++)
new (&B[i]) A(7);
即它使用未初始化的存储和新位置来构造元素。
所以你的直觉是错误的,矢量已经具有你所寻求的表现。每个元素调用一次构造函数,并且不需要默认构造函数。
答案 2 :(得分:2)
请考虑
之间的效果问题
你对实际的实施是错误的。在C ++ 11中,std::vector
有一个Allocator对象,默认情况下为std::allocator
。它首先通过调用Allocator::allocate
来初始化内存,Allocator::construct
返回原始内存;然后它调用{{1}}在原始内存上逐个构造对象,默认情况下使用placement new。换句话说,它与您指出的第二种可能的实现基本相同。
答案 3 :(得分:1)
对于pre-C ++ 11,你可以这样做:
new A[8]{ A(7), A(7), A(7), A(7), A(7), A(7), A(7), A(7) };
答案 4 :(得分:-1)
你试过for_each和lambda吗?
A* B = new A[8];
std::for_each(B, B+8, [](A &elem) {
elem.n = 7;
});