简体   繁体   English

我打算调用initializer_list构造函数,如果存在,则预先调用复制构造函数:为什么?

[英]I intend to call initializer_list constructor, and copy constructor is called beforehand if it exists: why?

The following type has three constructors. 以下类型有三个构造函数。 Note that one of them takes an initializer list of elements of that very same type. 请注意,其中一个采用了相同类型的元素的初始化列表。

struct Foo {
    Foo() {
        std::cout << "default ctor" << std::endl;
    }
    Foo(const Foo&) {
        std::cout << "copy ctor" << std::endl;
    }
    Foo(std::initializer_list<Foo>) {
        std::cout << "initializer_list<Foo>" << std::endl;
    }
};

While initializing an object using an initializer_list, I am surprised to see the copy constructor is automatically called as many times as there are elements in the initializer_list. 在使用initializer_list初始化对象时,我很惊讶地看到复制构造函数被自动调用的次数与initializer_list中的元素一样多。 Afterwards, the initializer_list constructor is called: 然后,调用initializer_list构造函数:

int main()
{
    Foo a;          // default ctor
    Foo b{a, a, a}; // copy ctor + copy ctor + copy ctor + initializer_list<Foo>
    return 0;
}

What are the reasons/justifications behind that behavior? 这种行为背后的原因/理由是什么? Note that if Foo had no copy constructor, the initialization Foo b{a, a, a} would apparently be perfectly possible (the initializer_list constructor would be the only one called). 注意,如果Foo没有复制构造函数,初始化Foo b{a, a, a}显然是完全可能的(initializer_list构造函数将是唯一被调用的构造函数)。

Full code here: http://coliru.stacked-crooked.com/a/f6e28dbb66746aa2 完整代码: http//coliru.stacked-crooked.com/a/f6e28dbb66746aa2

What are the reasons/justifications behind that behavior? 这种行为背后的原因/理由是什么?

The expression {a, a, a} (in your example) constructs a std::initializer_list<Foo> . 表达式{a, a, a} (在您的示例中)构造了一个std::initializer_list<Foo>

Each element of that array (yeah, you can intend an initializer list like a lightweight array) is construct as a copy of the object a . 该数组的每个元素(是的,您可以将初始化列表视为轻量级数组)构造为对象a副本

Indeed, the copy constructor of that class is called three times in order to construct exactly three copies. 实际上,该类的复制构造函数被调用三次,以便构造正好三个副本。


Note that if Foo had no copy constructor, the initialization Foo b{a, a, a} would apparently be perfectly possible (the initializer_list constructor would be the only one called). 注意,如果Foo没有复制构造函数,初始化Foo b {a,a,a}显然是完全可能的(initializer_list构造函数将是唯一被调用的构造函数)。

That's no true. 那不是真的。 If Foo "has no copy constructor", the compiler will provide a default one. 如果Foo “没有复制构造函数”,编译器将提供默认值。 So in that case the copy constructor will be still called three times, as in the previous example. 因此,在这种情况下,复制构造函数仍将被调用三次,如上例所示。

You can prove it just deleting the default copy constructor. 您可以证明它只是删除默认的复制构造函数。

From your example: 从你的例子:

struct Bar {
  // ...
  Bar(const Bar&) = delete;
};

In this way, there is no copy constructor and code will not compile because of the error: 这样,没有复制构造函数,由于错误,代码将无法编译:

use of deleted function 'Bar::Bar(const Bar&)'
     std::cout << "d : "; Bar d{c, c, c};

Indeed, it is not possible to construct the initializer list as usual. 实际上,不可能像往常一样构造初始化列表。


Final Conclusions 最终结论

There is no mystery in that. 这没有什么神秘之处。 You want to construct a "list" of three object. 你想构建一个三个对象的“列表”。 The compiler has to construct those object making copies from a . 编译器必须构造那些从a创建副本的对象。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM