另一个C ++问题,我试图弄清楚在构造对象时使用“=”有什么影响。考虑:
class Foo {
private:
int bar;
int baz;
public:
Foo(int bar, int baz)
:bar(bar), baz(baz) {}
};
int main() {
Foo foo1{4, 2};
Foo foo2 = {4, 2};
Foo foo3 = Foo{4, 2}; // I prefer this one for aesthetic reasons.
return 0;
}
有什么区别,我应该坚持哪种最佳做法?
此外,虽然我们讨论的是最佳实践主题,但我听说将explicit
添加到构造函数是一个好主意™,因为隐式转换具有奇怪的行为。所以我将explicit
添加到Foo
的构造函数中:
public:
explicit Foo(int bar, int baz)
:bar(bar), baz(baz) {}
突然,这:
Foo foo2 = {4, 2};
无法使用错误进行编译:
error: chosen constructor is explicit in copy-initialization
为什么?
答案 0 :(得分:8)
有什么不同
Foo foo1{4, 2};
在以下情况下执行直接初始化:
2)在列表初始化序列期间,如果没有提供初始化列表构造函数并且可以访问匹配的构造函数,则所有必要的隐式转换都是非缩小的。
Foo foo2 = {4, 2};
这是copy list initialization (6)。对于非直接列表初始化,不考虑显式构造函数。这就解释了为什么当你明确地改变构造函数时程序没有编译。
copy-list-initialization(只能调用非显式构造函数)
6)在等号后用braced-init-list初始化命名变量
Foo foo3 = Foo{4, 2};
这是临时对象的direct list initialization (2),然后是临时对象的copy initialization (1)。
direct-list-initialization(考虑显式和非显式构造函数)
2)使用braced-init-list
初始化未命名的临时文件在以下情况下执行复制初始化:
2)当声明非引用类型T的命名变量(自动,静态或线程局部)时,初始化程序由等号后跟表达式组成。
首先是最简单的,这就是我喜欢它的原因。
第二个需要一个隐式构造函数,但在其他方面没问题。
第三个涉及重复类型(违反DRY),并构造一个不必要的临时(实际上,优化器可能会删除该副本,但该类型必须是可复制的。)
我听说明确加入构造函数是一个好主意™。所以我向Foo
的构造函数添加了显式
如果要阻止隐式转换,则向单个参数构造函数添加显式是个好主意。对于两个参数构造函数,显式不是那么普遍有用,但我不怀疑可能存在需要它的情况。