对 c++11 统一初始化语法的天真、乐观和哦.. 如此错误的看法
我认为既然 C++11 用户定义类型对象应该使用新{...}
语法而不是旧(...)
语法构造(除了构造函数重载 forstd::initializer_list
和类似参数(例如std::vector
:size ctor vs 1 elem init_list ctor))。
好处是:没有狭窄的隐式转换,最麻烦的解析没有问题,一致性(?)。我认为没有问题,因为我认为它们是相同的(除了给出的示例)。
但他们不是。
一个纯粹疯狂的故事
{}
调用默认构造函数。
... 除非:
- 默认构造函数被删除并且
- 没有定义其他构造函数。
然后看起来它宁愿值初始化对象?...即使对象已经删除了默认构造函数,{}
也可以创建一个对象。这难道不是破坏了已删除构造函数的全部目的吗?
...除了以下情况:
- 该对象有一个已删除的默认构造函数,并且
- 定义了其他构造函数。
然后它失败了call to deleted constructor
。
...除了以下情况:
- 该对象有一个已删除的构造函数,并且
- 没有定义其他构造函数并且
- 至少是一个非静态数据成员。
然后它因缺少字段初始化程序而失败。
但是你可以使用它{value}
来构造对象。
好的,也许这与第一个异常相同(值初始化对象)
...除了以下情况:
- 该类有一个已删除的构造函数
- 并且至少有一个数据成员在类内默认初始化。
那么也不{}
也{value}
不能创建对象。
我确定我错过了一些。具有讽刺意味的是,它被称为统一初始化语法。我再说一遍:UNIFORM初始化语法。
这是什么疯狂?
方案 A
删除了默认构造函数:
struct foo {
foo() = delete;
};
// All bellow OK (no errors, no warnings)
foo f = foo{};
foo f = {};
foo f{}; // will use only this from now on.
方案 B
删除默认构造函数,删除其他构造函数
struct foo {
foo() = delete;
foo(int) = delete;
};
foo f{}; // OK
方案 C
删除了默认构造函数,定义了其他构造函数
struct foo {
foo() = delete;
foo(int) {};
};
foo f{}; // error call to deleted constructor
方案 D
已删除默认构造函数,未定义其他构造函数,数据成员
struct foo {
int a;
foo() = delete;
};
foo f{}; // error use of deleted function foo::foo()
foo f{3}; // OK
方案 E
删除了默认构造函数,删除了 T 构造函数,T 数据成员
struct foo {
int a;
foo() = delete;
foo(int) = delete;
};
foo f{}; // ERROR: missing initializer
foo f{3}; // OK
方案 F
删除了默认构造函数,类内数据成员初始化器
struct foo {
int a = 3;
foo() = delete;
};
/* Fa */ foo f{}; // ERROR: use of deleted function `foo::foo()`
/* Fb */ foo f{3}; // ERROR: no matching function to call `foo::foo(init list)`