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

时间:2016-07-17 09:34:38

标签: c++ c++11 constructor initialization initializer-list

另一个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

为什么?

1 个答案:

答案 0 :(得分:8)

  

有什么不同

Foo foo1{4, 2};

这是direct initialization (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

的构造函数添加了显式

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