5

更新:

上面的链接和下面的答案没有回答为什么这个功能没有标准化。这正是让我想知道的原因。请考虑和之间的性能问题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);FASTERstd::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++ 标准不支持这么方便的功能?理由是什么?

4

5 回答 5

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);

也就是说,它使用未初始化的存储和放置 new 来构造元素。

所以你的直觉是错误的,vector 已经有了你想要的性能。每个元素调用一次构造函数,不需要默认构造函数。

于 2013-09-17T03:54:42.523 回答
3

为什么 C++ 标准不支持这么方便的功能?理由是什么?

因为有更好的替代方案可以在(几乎)所有用例中替换内置数组(是的,甚至用于传递给 C-API):std::vector对于动态数组(使用 分配new)和std::array堆栈分配的数组。

使用std::vector,您可以使用std::vector<A> arr(8, 7)(正如 WhozCraig 评论的那样)创建一个包含 8 个元素的向量,用 7 初始化每个元素。省略第二个参数将使用它们的默认构造函数(内置类型使用0or初始化false)。

除了这个和其他便利功能(特别是自动调整大小 / )之外,创建数组push_back()的最大优势在于它遵守RAII,这意味着它一旦离开范围就会自动成为对象/内存 - 无论是否通过“掉出函数的末尾”、语句、,或抛出异常。std::vectornewdelete[]returnbreakcontinuegoto

于 2013-09-16T17:04:18.597 回答
2

请考虑之间的性能问题

你对实际实现是错误的。在 C++11 中,std::vector有一个 Allocator 对象,默认情况下是std::allocator. 它首先通过调用初始化内存Allocator::allocate,返回原始内存;然后它调用Allocator::construct在原始内存上一一构造对象,默认使用placement new。换句话说,它与您指出的第二种可能的实现基本相同。

于 2013-09-17T01:59:55.547 回答
1

对于 C++11 之前的版本,您可以这样做:

new A[8]{ A(7), A(7), A(7), A(7), A(7), A(7), A(7), A(7) };
于 2013-09-16T16:51:46.053 回答
-1

你试过for_each和 lambda 吗?

A* B = new A[8];

std::for_each(B, B+8, [](A &elem) {
    elem.n = 7;
});
于 2013-09-16T17:13:12.577 回答