簡體   English   中英

VS2013默認初始化vs值初始化

[英]VS2013 default initialization vs value initialization

請考慮以下代碼

struct B
{
    B() : member{}{};
    int member[10];
};

int main()
{
    B b;
}

VS2013編譯器發出以下警告:

警告C4351:新行為:數組'B :: member'的元素將默認初始化1> test.vcxproj - > C:\\ Users \\ asaxena2 \\ documents \\ visual studio 2013 \\ Projects \\ test \\ Debug \\ test.exe

在此處記錄

使用C ++ 11,並應用“默認初始化”的概念,意味着B.member的元素將不會被初始化。

但我相信member{}應該執行值初始化而不是默認初始化。 VS2013編譯器壞了嗎?

$ 7.0 / 6

默認初始化類型為T的對象意味着: - 如果T是(可能是cv限定的)類類型(第9節),則調用T的默認構造函數(如果T沒有可訪問的默認值,則初始化是錯誤的構造函數);
- 如果T是數組類型,則每個元素都是默認初始化的;
- 否則,不執行初始化。
如果程序要求對const -qualified類型T的對象進行默認初始化,則T應為具有用戶提供的默認構造函數的類類型。

$ 8.5.1

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

如果列表中的initializer-clause少於聚合中的成員,則未顯式初始化的每個成員都應從空的初始化列表(8.5.4)初始化。 [ 例如:

  struct S { int a; const char* b; int c; }; S ss = { 1, "asdf" }; 

初始化ss.a1ss.b"asdf" ,和ss.c與以下形式的表達式的值int()即, 0 - 末端的例子 ]

它似乎是一個措辭不正確的警告信息(我很驚訝它首先打印一個警告),但行為是正確的 B::member正在初始化值,對於int數組,它將變為零初始化。 這可以通過以下方式證明:

#include <iostream>

struct B
{
    B() : member{}{};
    int member[10];
};

struct C
{
    C() {};
    int member[10];
};

int main()
{
    B b;
    for(auto const& a : b.member) std::cout << a << ' ';
    std::cout << std::endl;

    C c;
    for(auto const& a : c.member) std::cout << a << ' ';
    std::cout << std::endl;
}

如果在Debug模式下編譯並運行,則會產生輸出:

0 0 0 0 0 0 0 0 0 0
-858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460 -858993460

第二行中的數字是0xCCCCCCCC ,VC ++編譯器在調試模式下填充內存的調試模式。 因此B::member被初始化為零,而沒有為C::member執行初始化。

免責聲明:我知道從未初始化的變量讀取是未定義的行為,但這是我能想到的最好的證明

編譯器警告不正確; 它實際上正在執行標准所要求的值初始化。

例:

#include <iostream>

struct B {
    B() : member{}{};
    int member[10];
};

int main() {
    int a[10] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
    B &b = *new (a) B;
    std::cout << b.member[9];  // prints '0'
}

MSDN頁面說:

C4351意味着您應該檢查您的代碼...如果您想要新的行為,可能是因為該數組已顯式添加到構造函數的成員初始化列表中,請使用警告編譯指示來禁用該警告。 對大多數用戶來說,新行為應該沒問題。

因此,您必須為一行添加#pragma warning (suppress:4351)或為整個文件添加#pragma warning (suppress:4351) #pragma warning (disable:4351)

暫無
暫無

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

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