需要帮助理解“{} -initializer语法可以最大限度地减少不幸转换的机会”

时间:2014-02-18 15:52:31

标签: c++ c++11

在“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 conversionsT v3 {f()};的评论works if and only if the type of f() can be implicitly converted to a T。考虑以下两种情况:

  • a)如果T有一个显式构造函数,它接受f()的类型的参数。
  • b)如果f()的类型具有某种类型X的转换运算符,而T的构造函数采用类型为X的参数。

对于这两种情况,f()的类型不能隐式转换为T,但T v3 {f()}格式正确,因此至少该注释的only if部分似乎不合适? (也不确定if部分是否正确。)
对于这两种情况,T v3 = f();都是格式错误的,那么句子minimize the chances for unfortunate conversions在这里意味着什么?似乎{} -initializer实际上接受了更多的转换形式(不管它是不幸还是不是另一个问题)。 (在v1的情况下说明了防止缩小,这很清楚。我对v3感到困惑。)

3 个答案:

答案 0 :(得分:0)

它实际上以其他方式进行转换,而不是默认转换。

使用您的一个示例,char x = 12345;实际上会将此值减少到最后8位,因为这是char的大小。使用{}表示法时,会出现错误,因为它不符合要求。

有时(ab)用于获取特殊效果,因此它在新C ++中保留为默认选项,而新标记用于提供更好的行为,错误空间更小。

答案 1 :(得分:0)

转换:

char v1 = 12345;

不幸的,因为它几乎肯定不是程序员想要的:

  • 要么我们想要一个可以代表值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()};
}

其中初始化将被诊断为格式错误,因为它为TLive demo at Coliru)选择了显式构造函数。