在对象构造中使用"="的效果

Mem*_*ter 2 c++ constructor initialization initializer-list c++11

另一个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;
}
Run Code Online (Sandbox Code Playgroud)

有什么区别,我应该坚持哪种最佳做法?

此外,虽然我们讨论的是最佳实践的主题,但我听说添加explicit构造函数是一个好主意™因为隐式转换的奇怪行为.所以我添加explicit到构造函数Foo:

    public:
        explicit Foo(int bar, int baz)
            :bar(bar), baz(baz) {}
Run Code Online (Sandbox Code Playgroud)

突然,这个:

    Foo foo2 = {4, 2};
Run Code Online (Sandbox Code Playgroud)

无法编译错误:

error: chosen constructor is explicit in copy-initialization
Run Code Online (Sandbox Code Playgroud)

这是为什么?

eer*_*ika 8

有什么区别

Foo foo1{4, 2};
Run Code Online (Sandbox Code Playgroud)

这是直接初始化(2).

在以下情况下执行直接初始化:

2)在列表初始化序列期间,如果没有提供初始化列表构造函数并且可以访问匹配的构造函数,则所有必要的隐式转换都是非缩小的.


Foo foo2 = {4, 2};
Run Code Online (Sandbox Code Playgroud)

这是复制列表初始化(6).对于非直接列表初始化,不考虑显式构造函数.这解释了为什么在更改构造函数显式时程序没有编译.

copy-list-initialization(只能调用非显式构造函数)

6)在等号后用braced-init-list初始化命名变量


Foo foo3 = Foo{4, 2};
Run Code Online (Sandbox Code Playgroud)

这是临时对象的直接列表初始化(2),然后从临时对象复制初始化(1).

direct-list-initialization(考虑显式和非显式构造函数)

2)使用braced-init-list初始化未命名的临时文件


在以下情况下执行复制初始化:

2)当声明非引用类型T的命名变量(自动,静态或线程局部)时,初始化器由等号后跟表达式组成.


首先是最简单的,这就是我喜欢它的原因.

第二个需要一个隐式构造函数,但在其他方面没有问题.

第三个涉及重复类型(违反DRY),并构造一个不必要的临时(实际上,优化器可能会删除副本,但类型必须是可复制的).

我听说为构造函数添加明确是一个好主意™.所以我向Foo的构造函数添加了显式

如果要阻止隐式转换,则向单个参数构造函数添加显式是个好主意.对于两个参数构造函数,显式并不是那么普遍有用,但我不怀疑可能存在需要它的情况.