簡體   English   中英

我打算調用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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM