【问题标题】:I intend to call initializer_list constructor, and copy constructor is called beforehand if it exists: why?我打算调用initializer_list构造函数,如果存在则预先调用复制构造函数:为什么?
【发布时间】:2018-01-27 22:48:05
【问题描述】:

以下类型具有三个构造函数。请注意,其中一个采用相同类型元素的初始化列表。

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;
    }
};

在使用 initializer_list 初始化对象时,我很惊讶地看到复制构造函数被自动调用的次数与 initializer_list 中的元素一样多。之后调用initializer_list构造函数:

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

这种行为背后的原因/理由是什么?请注意,如果 Foo 没有复制构造函数,那么初始化 Foo b{a, a, a} 显然是完全可能的(initializer_list 构造函数将是唯一调用的构造函数)。

完整代码在这里:http://coliru.stacked-crooked.com/a/f6e28dbb66746aa2

【问题讨论】:

  • bar-example 中,仍然调用了复制构造函数,但是您“看不到”,因为它是默认值。
  • “显然是完全可能的” - 不正确。试试Foo(const Foo&amp;) = delete;
  • Biagio Festa,Yuval Ben-Arie,感谢您的 cmets,这就是我需要的信息!

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


【解决方案1】:

这种行为背后的原因/理由是什么?

表达式{a, a, a}(在您的示例中)构造了一个std::initializer_list&lt;Foo&gt;

该数组的每个元素(是的,您可以像轻量级数组一样使用初始化列表)构造为对象a副本

确实,该类的复制构造函数被调用了3次,以便精确地构造三个副本。


请注意,如果 Foo 没有复制构造函数,初始化 Foo b{a, a, a} 显然是完全可能的(initializer_list 构造函数将是唯一被调用的构造函数)。

这不是真的。如果Foo“没有复制构造函数”,编译器将提供一个默认值。因此,在这种情况下,复制构造函数仍将被调用 3 次,如上例所示。

你可以证明它只是删除默认的复制构造函数。

从你的例子:

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

这样就没有拷贝构造函数,代码也不会因为报错而编译:

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

确实,不可能像往常一样构造初始化列表。


最终结论

这并不神秘。 您想构建三个对象的“列表”。编译器必须构造那些从a 复制的对象。

【讨论】:

    猜你喜欢
    • 2021-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-28
    • 2021-02-12
    • 2012-02-28
    • 1970-01-01
    • 2021-02-18
    相关资源
    最近更新 更多