**:
初始化:建立變數時賦予其乙個初始值。
賦值:把物件(已經建立)的當前值擦除,而用乙個新值來代替。
int a = ; // 列表初始化方式1
int a; // 列表初始化方式2
說明:上述的兩種方式都可以將變數a初始化為0。
當對內建型別使用列表初始化時,若初始值存在丟失的風險,編譯將報錯,如:
int a = 3.14; // 正確,雖然會丟失小數部分,但是編譯器不報錯。
int a = ; // 錯誤,因為將會丟失小數部分(其實,g++只是對此提示警告而已,並非錯誤)。
使用g++ 4.8.4對上述兩個初始化方式分別進行測試,前者無錯誤無警告,但是後者提示警告(不是錯誤!):
[cpp] view plain copy
warning: narrowing conversion of 『3.1400000000000001e+0』 from 『double』 to 『int』 inside [-wnarrowing]
參考資料[1]p39還提到,由花括號括起來的初始值,不僅可以用於初始化變數,還可以用於為物件(舊變數)賦新值。
[cpp] view plain copy
int a = 1; // 定義變數,並且初始化為1
a = ; // 為變數a賦新值3
可以用在任何需要變數初始化的地方,例如第6章的類成員初始化,以及在for()
中定義的變數:
[cpp] view plain copy
for (int i; i < 10; i++)
[cpp] view plain copy
string s1; // 預設初始化為空字串
string s2 = s1; // 拷貝初始化,s2是s1的副本
[cpp] view plain copy
string s1(); // 直接初始化為空字串
string s2("hi"); // 直接初始化
string s3(3, 'c'); // 直接初始化,s2的內容是ccc
參考資料[1]p89指出,使用圓括號提供初值是用來構造(construct)物件,因此可以知道,所謂的直接初始化就是顯式的呼叫相應的建構函式。參考資料[1]p262歸納了值初始化的3種情況:
在陣列初始化過程中如果提供的初值數量少於陣列大小時;
當不使用初始值定義乙個區域性靜態變數時;
當通過t()形式的表示式顯式地請求值初始化時(t是型別名)。
參考資料[1]p265指出,explicit建構函式只能用於直接初始化。
vector使用直接初始化時,需要指定乙個重複次數:
[cpp] view plain copy
vector
v1("hello", "world"); // 錯誤
vector
v2; // 正確,可以列表初始化
vector
v3(2, "hello"); // 正確,直接初始化要指定乙個重複次數,此處v3初始化為"helloheloo"
有時候,就算是用的是花括號,也是起到直接初始化的作用(相當於圓括號):
[cpp] view plain copy
vector
v4; // 直接初始化,v4有10預設初始化的元素
vector
v5;// 直接初始化,v5有10個值為「hi」的元素
原則:參考資料[1]p89指出,初始化過程會盡可能地把花括號內的值當成是元素初始值列表來處理(列表初始化),只有無法執行列表初始化時才會考慮其他初始化方式。
參考資料[1]p40指出,如果定義變數時沒有指定初值,則變數被預設初始化,具體值由變數型別及其所在位置決定。參考資料[1]p262歸納了發生預設初始化的3種情況。
5.1.1.1 非static區域性變數
參考資料[1]p40指出,在函式體內部的內建型別變數(包括指標 )將不被初始化。參考資料[1]p47指出,其它內建型別一樣,在塊作用域內定義的指標如果沒有被初始化,也將擁有乙個不確定的值。參考資料[1]p185介紹自動物件的時候,也指出這個問題。
5.1.1.2 static區域性變數
參考資料[1]p185指出,如果區域性變數沒有顯式的初始化值,它將執行值初始化(不是預設初始化!),內建型別的區域性靜態變數初始化為0。
初始化為0。
參考資料[1]p236指出,類通過乙個特殊的建構函式來控制預設初始化過程,這個類叫做預設建構函式。預設建構函式無需任何實參。參考資料[1]p637也指出,每個類各自定義其初始化物件的方式(預設建構函式)。例如,std::string,不管是定義於區域性還是全域性,都會預設初始化為空。
[cpp] view plain copy
string a; // 預設初始化為空字串
tuple
threed; // 使用tuple的預設建構函式對每個成員進行值初始化
參考資料[1]p89指出,有些類不支援預設初始化,必須明確地提供初始值。根據參考資料[1]p236的說明可猜測,此類無缺省建構函式。例如下面的定義,將會出現編譯錯誤。
[cpp] view plain copy
class person // 而person中並沒有顯式定義預設
// 建構函式,因此person沒有預設
// 建構函式!
private:
const
string name;
const
string addr;
};
int main(void)
[cpp] view plain copy
test.cpp|36 col 9| error: no matching function
forcall
to 『person::person()』
參考資料[1]p88提到了值初始化的例子,只提供vector物件容納元素數量而不提供初始值,此時會建立乙個值初始化的元素初值,並把它賦給容器中的所有元素。這個初值由vector物件中元素的型別決定:
[cpp] view plain copy
vector
ivec(10); // 10個元素,每個都初始化為0
參考資料[1]p262則指出,物件預設初始化或值初始化時自動執行預設建構函式。
參考資料[1]p65指出,c++11新標準規定,可以為類內資料成員提供乙個類內初始值。參考資料[1]p88則指出,類內初始值只能使用拷貝初始化和列表初始化(不能直接初始化)。參考資料[1]p246則指出,當我們提供乙個類內初始值時,必須以符號=或者花括號表示。沒有提供類內初始值的成員將被預設初始化。
[cpp] view plain copy
class
a ; // 列表初始化為0
int b = ; // 列表初始化為1
int c = 2; // 傳統初始化為2
int d; // 預設初始化,具體值未定義
int e(3); // 錯誤:不能將初始值放在括號內(直接初始化)!
};
[1]c++ primer中文版(第5版) C 11 就地初始化與列表初始化
在 c 11 之前,只能對結構體或類的靜態常量成員進行就地初始化,其他的不行。class c class c or int b c 11 only int c 7 error 注意,小括號初始化方式不能用於就地初始化。c 11 支援了就地初始化非靜態資料成員的同時,初始化列表的方式也被保留下來,也就...
c 11 就地初始化與列表初始化
還可以看看 在c 11之前,只能對結構體或類的靜態常量成員進行就地初始化,其他的不行。class c class c 或int b c 11 only int c 7 error 1.2就地初始化與初始化列表的先後順序 c 11標準支援了就地初始化非靜態資料成員的同時,初始化列表的方式也被保留下來,...
C 11初始化與構造
研究vector容器使用方法時,初始化與構造需要區分 初始化不是賦值,初始化的含義是建立變數時賦予其初始值,賦值,則是將物件當前值擦除,用新值替代 拷貝初始化與直接初始化是一對概念,特徵為使用等號是拷貝初始化 copy initialization 把等號右側的值賦值到新建物件中去,右側是值,一般在...