[英]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.a
與1
,ss.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'
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.