簡體   English   中英

顯式默認構造函數

[英]Explicit default constructor

此代碼與GCC 5.X,MSVC編譯良好,但GCC 6.X給出錯誤:

“從初始化列表轉換為'a'將使用顯式構造函數'a :: a()'” ,clang “選擇的構造函數在復制初始化中是顯式的”

刪除explicit或更改為ac{}修復了問題,但我很好奇為什么它以這種方式工作。

class a
{
public:
    explicit a () {}
};
struct b
{
    a c;
};

int main() {
    b d{};
}

b是一個聚合 使用初始化列表初始化它時,列表中的元素將初始化聚合的前n個成員,其中n是列表中元素的數量。 聚合的其余元素是copy-list-initialized

所以在你的例子中, c將被copy-list-initialized ,但是如果選擇的構造函數是explicit ,那么這是錯誤的,因此錯誤。

相關的標准報價是

[dcl.init.aggr] / 3

當聚合由[dcl.init.list]中指定的初始化列表初始化時,初始化列表的元素將被視為聚合元素的初始化器。 聚合的顯式初始化元素確定如下:
...
- 如果初始化列表是初始化列表 ,則聚合的顯式初始化元素是聚合的前n個元素,其中n是初始化列表中的元素數。
- 否則,初始化列表必須為{} ,並且沒有顯式初始化的元素。

[dcl.init.aggr] / 5

對於非聯合聚合,每個不是顯式初始化元素的元素都初始化如下:
...
- 否則,如果元素不是引用,則從空的初始化列表([dcl.init.list])復制初始化該元素。

從空初始化列表中復制初始化c的效果描述於

[dcl.init.list] / 3

列表初始化對象或類型T引用定義如下:
...
- 否則,如果初始化列表沒有元素且T是具有默認構造函數的類類型,則對象將進行值初始化。

[dcl.init] / 8

類型T的對象進行值初始化意味着:
...
- 如果T是一個(可能是cv限定的)類類型,沒有默認構造函數([class.ctor])或者是用戶提供或刪除的默認構造函數,那么該對象是默認初始化的;

[dcl.init] / 7

默認初始化 T類型的對象意味着:
- 如果T是(可能是cv限定的)類類型,則考慮構造函數。 枚舉適用的構造函數([over.match.ctor]),並通過重載決策選擇初始化程序()的最佳構造函數。 使用空參數列表調用如此選擇的構造函數來初始化對象。

[over.match.ctor]

...對於復制初始化,候選函數是該類的所有轉換構造函數。

[class.conv.ctor] / 1

聲明沒有函數說明符 explicit構造函數指定從其參數類型(如果有)到其類的類型的轉換。 這樣的構造函數稱為轉換構造函數

在上面的示例中, a沒有轉換構造函數,因此重載解析失敗。 [class.conv.ctor] / 2中的(非規范)示例甚至包含一個非常類似的情況

  struct Z { explicit Z(); explicit Z(int); explicit Z(int, int); }; Z c = {}; // error: copy-list-initialization 

您可以通過為c提供默認成員初始值設定項來避免錯誤

struct b
{
    a c{};  // direct-list-initialization, explicit ctor is OK
};

暫無
暫無

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

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