在“The C ++ Programming Language”第4版第164页中:
当我们明确提到我们正在初始化的对象的类型时, 我们有两种类型需要考虑:对象的类型和类型 初始化器。例如:
char v1 = 12345; // 12345 is an int int v2 = 'c'; // 'c' is a char T v3 = f();
通过对此类定义使用{} -initializer语法,我们将其最小化 不幸转换的可能性:
char v1 {12345}; // error : narrowing int v2 {'c'}; // fine: implicit char->int conversion T v3 {f()}; // works if and only if the type of f() can be implicitly converted to a T
我不太明白句子minimize the chances for unfortunate conversions
和T v3 {f()};
的评论works if and only if the type of f() can be implicitly converted to a T
。考虑以下两种情况:
对于这两种情况,f()的类型不能隐式转换为T,但T v3 {f()}
格式正确,因此至少该注释的only if
部分似乎不合适? (也不确定if
部分是否正确。)
对于这两种情况,T v3 = f();
都是格式错误的,那么句子minimize the chances for unfortunate conversions
在这里意味着什么?似乎{} -initializer实际上接受了更多的转换形式(不管它是不幸还是不是另一个问题)。 (在v1
的情况下说明了防止缩小,这很清楚。我对v3
感到困惑。)
答案 0 :(得分:0)
它实际上以其他方式进行转换,而不是默认转换。
使用您的一个示例,char x = 12345;
实际上会将此值减少到最后8位,因为这是char的大小。使用{}
表示法时,会出现错误,因为它不符合要求。
有时(ab)用于获取特殊效果,因此它在新C ++中保留为默认选项,而新标记用于提供更好的行为,错误空间更小。
答案 1 :(得分:0)
转换:
char v1 = 12345;
是不幸的,因为它几乎肯定不是程序员想要的:
对于v3
同样适用,但是在更复杂的背景下。第一个片段将强制编译器考虑用户定义的转换序列。这增加了错误的可能性;毕竟,我们可能会错误地实施转换操作符,输入错误信息,或者设法在方孔中安装圆形挂钩。使用复制列表初始化,我们排除了用户定义的转换序列,使转换更加安全。
有关为何发生这种情况的示例和详细说明,请参阅this question。
答案 2 :(得分:0)
初始化v3
的评论:
T v3 {f()}; // works if and only if the type of f() can be implicitly converted to a T
不严格正确。当且仅当f()
的类型可以明确地转换为T
时,该初始化才有效。语法如下:
T v3 = {f()}; // truly does work if and only if the type of f()
// can be implicitly converted to a T
(copy-list-initialization而不是direct-list-initialization)确实需要转换是隐式的。这个程序说明了不同之处:
struct T {
explicit T(int) {}
};
int f() { return 0; }
int main() {
T v3 = {f()};
}
其中初始化将被诊断为格式错误,因为它为T
(Live demo at Coliru)选择了显式构造函数。