像這樣的代碼,
#include <iostream>
class obj
{
public:
int v;
};
int main(int argc, char *argv[])
{
obj o1;
std::cout << o1.v << std::endl; // print 32766, indeterminate values
obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?
int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
return 0;
}
我知道全域或靜態變數將初始化為零。
并且自動執行不確定的值。
但是堆物件使用new關鍵字,有什么參考解釋嗎?
uj5u.com熱心網友回復:
來自 C 17 標準(11.6 初始化程式)
11 初始化器為空括號集的物件,即 (),應進行值初始化。
對于 int 等基本型別,它意味著零初始化。
所以在這個宣告中
obj *o2 = new obj();
動態分配物件的資料成員v是零初始化的。
至于這個代碼片段
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
然后指標指向的物件v2沒有初始化,下一個輸出陳述句可以輸出存盤在分配新物件的記憶體范圍中的任何值。
uj5u.com熱心網友回復:
obj *o2 = new obj();是值初始化,意味著物件將被零初始化,因此資料成員v將被初始化為0.
這可以從值初始化中看出:
這是使用空初始化程式構造物件時執行的初始化。
new T () (2)2,6) 當具有動態存盤持續時間的物件由 new 運算式創建時,初始化器由一對空括號或大括號組成 (C 11 起);
另一方面,
int *v2 = new int; //this uses default initialization
std::cout << *v2 << std::endl; //this is undefined behavior
以上導致未定義的行為,因為您正在取消參考v2并且分配的int物件未初始化,因此具有不確定的值。
未定義的行為意味著任何事情都可能發生。但永遠不要依賴(或基于)具有 UB 的程式的輸出。該程式可能會崩潰。
這可以從默認初始化中看出:
這是在沒有初始化器的情況下構造物件時執行的初始化。
new T (2)當具有動態存盤持續時間的物件由沒有初始化程式的新運算式創建時;
默認初始化的效果是:
- 否則,不執行初始化:具有自動存盤持續時間的物件(及其子物件)包含不確定的值。
uj5u.com熱心網友回復:
第 1、3、4 種情況是默認初始化,因為它們被初始化為不確定值;注意也0屬于不確定值。
第二種情況是值初始化,因為物件將被零初始化,這意味著o2->v保證是0。
如果 T 是一個具有既不是用戶提供也不是洗掉的默認建構式的型別別(也就是說,它可能是一個具有隱式定義或默認的默認建構式的類),則該物件是零初始化的,并且默認的語意約束-檢查初始化,如果 T 有一個非平凡的默認建構式,則該物件是默認初始化的;
另一方面,如果將第 4 種情況更改為int *v2 = new int();,即值初始化,*v2也將被零初始化為0。
uj5u.com熱心網友回復:
初始化規則是一團糟。因此,讓我們繞過他們并強制解決問題:
class obj
{
public:
int v{};
};
在那里,現在v總是要被初始化。如果您添加一個未初始化的建構式,這甚至可以作業,v因為編譯器會自動添加成員初始化。
至于為什么你的代碼表現得如此:
obj o1;
std::cout << o1.v << std::endl; // print 32766, indeterminate values
o1在堆疊(或實際上是一個暫存器)上創建并默認初始化。這int意味著沒有初始化。堆疊(或暫存器)中的任何隨機資料都是您得到的。
obj *o2 = new obj();
std::cout << o2->v << std::endl; // print 0,but why?
來自 C 17 標準(11.6 初始化程式):
11 初始化器為空括號集的物件,即 (),應進行值初始化。
的值初始化將int其設定為 0。
int v1;
std::cout << v1 << std::endl; // print 22024, indeterminate values
默認初始化,你會得到隨機資料。
int *v2 = new int;
std::cout << *v2 << std::endl; // print 0,but why?
默認初始化,你會得到隨機資料。新分配的記憶體恰好是 0,除非它被應用程式重用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/480879.html
