【发布时间】:2017-07-07 15:49:32
【问题描述】:
如何在不复制或移动构造临时元素的情况下初始化数组?当元素具有明确的deleted 复制或移动构造函数时,只有当元素具有默认 ctor 或具有所有默认参数的 ctor 并且我执行以下操作之一时,我才能初始化数组: (a) 明确声明数组, (b) 直接初始化和零初始化数组,或 (c) 复制初始化和零初始化数组。直接(但非零)初始化和复制(但非零)初始化均无法编译。
struct Foo
{
Foo(int n = 5) : num(n) {}
Foo(const Foo&) = delete;
//Foo(Foo&&) = delete; // <-- gives same effect
int num;
};
int main()
{
// Resultant arrays for 'a1', 'a2', and 'a3' are two
// 'Foo' elements each with 'num' values of '5':
Foo a1[2]; // plain declaration
Foo a2[2] {}; // direct initialization and zero initialization
Foo a3[2] = {}; // copy initialization and zero initialization
Foo a4[2] {5, 5}; // direct initialization -> ERROR
Foo a5[2] = {5, 5}; // copy initialization -> ERROR
}
- 这 3 种方式是唯一在不复制/移动临时元素的情况下初始化数组的方式吗?
-
a1、a2和a3是否算作初始化?例如a1是一个声明,但它的元素获取初始值,尽管是默认值。 - 其中有错误吗?我用 C++14 标志做了这个 GCC 6.3.0。
- 为什么复制初始化与零初始化相结合仍然在复制初始化的范畴下工作?
- 一般来说,所有数组初始化都是用花括号来构造临时元素(除非在没有删除复制或移动构造函数时省略(或者省略不适用于数组?))通过每个元素的复制、移动或复制和移动构造的混合?
【问题讨论】:
-
Foo a[] = { Foo(5), Foo(5) };怎么样? -
请注意,C++17 已保证复制省略,因此 C++14 中的一些非良构案例将变为良构。
-
@KerrekSB ,
Foo a[] = { Foo(5), Foo(5) };给error: use of deleted function 'Foo::Foo(const Foo&)' -
没有“复制零”和“直接零”初始化之类的东西。这些是复制列表初始化和带有空列表的直接列表初始化。而且它们绝不是零初始化,因为
Foo将由其构造函数初始化。 -
Visual C++ 2015 update 2 编译直接初始化就好了。
标签: c++ arrays in-place copy-elision deleted-functions