[英]C++ Copy constructor gets called instead of initializer_list<>
[英]I intend to call initializer_list constructor, and copy constructor is called beforehand if it exists: why?
以下類型有三個構造函數。 請注意,其中一個采用了相同類型的元素的初始化列表。
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
這種行為背后的原因/理由是什么?
表達式{a, a, a}
(在您的示例中)構造了一個std::initializer_list<Foo>
。
該數組的每個元素(是的,您可以將初始化列表視為輕量級數組)構造為對象a
的副本 。
實際上,該類的復制構造函數被調用三次,以便構造正好三個副本。
注意,如果Foo沒有復制構造函數,初始化Foo b {a,a,a}顯然是完全可能的(initializer_list構造函數將是唯一被調用的構造函數)。
那不是真的。 如果Foo
“沒有復制構造函數”,編譯器將提供默認值。 因此,在這種情況下,復制構造函數仍將被調用三次,如上例所示。
您可以證明它只是刪除默認的復制構造函數。
從你的例子:
struct Bar {
// ...
Bar(const Bar&) = delete;
};
這樣,沒有復制構造函數,由於錯誤,代碼將無法編譯:
use of deleted function 'Bar::Bar(const Bar&)'
std::cout << "d : "; Bar d{c, c, c};
實際上,不可能像往常一樣構造初始化列表。
最終結論
這沒有什么神秘之處。 你想構建一個三個對象的“列表”。 編譯器必須構造那些從a
創建副本的對象。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.