簡體   English   中英

如何使用已刪除的復制構造函數初始化類數組(C ++ 11)

[英]How to initialize array of classes with deleted copy constructor (C++11)

關於為什么我不能初始化對象數組(如果它們有私有拷貝構造函數)的現有問題 特指C ++ 03。 我從那個問題中知道我在C ++ 03中不允許做什么,但我認為它應該可以在C ++ 11中實現

我有一個不可移動的類(稱之為Child),我需要在另一個類的構造函數中初始化一個Child數組(稱之為Parent)。 “不可移動”是指在該對象的生命周期內,Child對象的地址必須保持不變。 這樣做的正確方法是什么?

使用C ++ 11,我嘗試了以下內容:

class Child
{
public:
    Child (int x) {}
    ~Child () {}

    Child (const Child &) = delete;
};

class Parent
{
public:
    Parent () : children {{5}, {7}} {}

private:
    Child children[2];
};

此代碼與Clang 3.5.0編譯良好,但GCC 4.9.1抱怨我正在嘗試使用已刪除的復制構造函數:

test.cc: In constructor ‘Parent::Parent()’:
test.cc:13:35: error: use of deleted function ‘Child::Child(const Child&)’
     Parent () : children {{5}, {7}} {}
                                   ^
test.cc:7:5: note: declared here
     Child (const Child &) = delete;
     ^

我已經讀過復制初始化和直接初始化之間的區別(例如這里這里 ),我想避免使用直接初始化來調用復制構造函數。 我的語法錯了嗎? 這是GCC中的錯誤嗎? 或者我正在嘗試做什么是不可能的?

我同意這似乎是GCC錯誤的評論(報告為63707 )。

當數組中的類型具有用戶定義的析構函數時,它只能編譯,這對我來說沒有意義。

我遇到了類似的問題,即這段代碼

#include <iostream>

class Widget {
public:
    Widget(int i) { std::cout << "Ctor " << i << std::endl; }

    Widget(const Widget&); // = delete;
};

int main() {
    Widget w = 123;
}

編譯並給出了預期的結果,但在取消注釋= delete它無法使用gcc-4.9進行編譯。

閱讀標准后,我認為答案在於8.5/16中最高壓痕的第二項,如下所述。

基本上什么似乎發生是編譯器概念要創建一個臨時類型的Widget直接初始化實際的對象w通過拷貝構造函數從暫時的。 由於復制構造函數被刪除,編譯停止。 如果沒有刪除復制構造函數,編譯器稍后會意識到它可能會刪除副本,但它沒有那么遠。

以下是相關部分:

[...] [...]復制初始化案例[...]用戶定義的轉換序列可以從源類型轉換為目標類型[...],如13.3.1.4所述進行枚舉,通過重載決策(13.3)選擇最好的一個。 [...]選擇的函數以初始化表達式作為參數調用; 如果函數是構造函數,則調用初始化目標類型的cv-nonqualified版本的臨時函數。 [...]然后,根據上面的規則,使用調用的結果(這是構造函數的臨時情況)直接初始化作為復制初始化目標的對象。 在某些情況下,允許實現通過將中間結果直接構造到正在初始化的對象中來消除此直接初始化中固有的復制; 見12.2,12.8。

但我可能錯了,因為[...]部分有很多我不明白的地方。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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