你的同事在使用 "统一初始化" 方面有些不足,当类型已知时不需要使用类型名称。例如,在创建返回值时。 Clone
可以这样定义:
Demo Clone() {
return {*this};
}
需要时,这将调用Demo
的拷贝构造函数。你认为这是不是更好,取决于你自己。
在GOTW 1中,Sutter提出了一项指南:
指南:倾向于使用初始化方式{ },例如vector v = {1, 2, 3, 4};或auto v = vector{1, 2, 3, 4};,因为它更一致、更正确,并且完全避免了必须了解旧式陷阱的问题。在单参数情况下,如果您只想看到=号,例如int i = 42;和auto x = anything;,省略花括号也可以。...
特别地,使用花括号可以避免以下混淆:
Demo d(); //function declaration, but looks like it might construct a Demo
Demo d{}; //constructs a Demo, as you'd expect
花括号语法将首先使用带有初始化器列表的构造函数(如果存在)。否则,它将使用普通构造函数。它还可以防止上面列出的令人困惑的解析机制的出现。
在使用复制初始化时也有不同的行为。使用标准方式
Demo d = x;
编译器有选项将
x
转换为
Demo
(如果需要),然后将转换后的右值移动/复制到
w
中。这类似于
Demo d(Demo(x));
,意思是调用了多个构造函数。
Demo d = {x};
这相当于 Demo d{x}
,并确保只调用一个构造函数。两个赋值都不能使用显式构造函数。
正如评论中提到的,有一些陷阱。对于那些接受initializer_list
并且有“普通”构造函数的类可能会引起混淆。
vector<int> v{5}; // vector containing one element of '5'
vector<int> v(5); // vector containing five elements.
return *this;
? - Aaron McDaidinitializer_list
构造函数,那么这会改变Clone
的行为吗?你的评论是在强调这一点,还是我漏掉了其他什么东西? - Rob