c++的初始化有很多方式:預設初始化,值初始化,直接初始化,拷貝初始化,列表初始化。這些方式之間有什麼區別與聯絡呢?我們一一來看。
預設初始化是指定義變數時沒有指定初值時進行的初始化操作。例如int a; sales_data mydata;等等。這些變數被定義了而不是僅僅被宣告(因為沒有extern關鍵字修飾),而且沒有顯式的賦予初值。特別的,如果採用動態分配記憶體的方式(即採用new關鍵字)建立的變數,不加括號時(如int *p=new int;)也是預設初始化,加了括號(如int *p=new int())為值初始化。變數的值與變數的型別與定義的位置有關係。
(1)對於內建型別變數(如int,double,bool等),如果定義在語句塊外(即{}外),則變數被預設初始化為0;如果定義在語句塊內(即{}內),變數將擁有未定義的值。
(2)對於類型別的變數(如string或其他自定義型別),不管定義於何處,都會執行預設建構函式。如果該類沒有預設建構函式,則會引發錯誤。因此,建議為每個類都定義乙個預設建構函式。
int a;
sales_data mydata;
vectorsvec;
string s;
值初始化是值使用了初始化器(即使用了圓括號或花括號)但卻沒有提供初始值的情況。例如,
int *p=new int();
// 對於vector而言,只提供了vector物件容納的元素數量而略去初始值
vectorsvec(10);
vectorivec(10);
等等都是典型的值初始化方式。注意,當不採用動態分配記憶體的方式(即不採用new運算子)時,寫成int a();是錯誤的值初始化方式,因為這種方式宣告了乙個函式而不是進行值初始化。如果一定要進行值初始化,必須結合拷貝初始化使用,即寫成int a=int();值初始化和預設初始化一樣,對於內建型別初始化為0,對於類型別則呼叫其預設建構函式,如果沒有預設建構函式,則不能進行初始化。
直接初始化與拷貝初始化對應,其內部實現機理不同。
直接初始化是指採用小括號的方式進行變數初始化(小括號裡一定要有初始值,如果沒提供初始值,那就是值初始化了!)。
int a(12);
sales_data mydata(para);
vectorivec(ivec2);//直接初始化對於vector容器而言,僅支援這樣的形式
string s("123456");
注意 vectorivec(10)是值初始化,並不是直接初始化。
拷貝初始化是指採用等號(=)進行初始化的方式。
int a=12;
sales_data mydata=para;
vectorivec=ivec2;
string s=string("123456");
拷貝初始化看起來像是給變數賦值,實際上是執行了初始化操作,與先定義再賦值本質不同。
(1)對於內建型別變數(如int,double,bool等),直接初始化與拷貝初始化差別可以忽略不計。
(2)對於類型別的變數(如string或其他自定義型別),直接初始化呼叫類的建構函式,拷貝初始化呼叫類的拷貝建構函式。
直接初始化不一定要呼叫拷貝建構函式,而拷貝初始化一定要呼叫拷貝建構函式。特別的,當對類型別變數進行初始化時,如果類的建構函式採用了explicit修飾而且需要隱式型別轉換時,則只能通過直接初始化而不能通過拷貝初始化進行操作。關於詳細介紹參考 c++的一大誤區——深入解釋直接初始化與複製初始化的區別
列表初始化是c++ 11 新引進的初始化方式,它採用一對花括號(即{})進行初始化操作。能用直接初始化和拷貝初始化的地方都能用列表初始化,而且列表初始化能對容器進行方便的初始化,因此在新的c++標準中,推薦使用列表初始化的方式進行初始化。
int a;
string s;
//對vector容器而言
vectorvec;
vectorv1;
這裡一定要注意,列表初始化使用的是花括號而不是圓括號!
建立指定數量的元素
還可以用vector物件容納的元素數量和所有元素的統一初始值來初始化vector物件:
vectorivec(10,-1);//10個int型別的物件,每個物件都被初始化為-1
vectorsvec(10,"hi!");//10個string物件,每個都是"hi!"
通常通過花括號或圓括號來區分初始化含義
vectorv1(10);//v1有10個元素,每個都為0
vectorv2;//v2有1個元素,為10
vectorv3(10,1);//v3有10個元素,每個都是1
vectorv4;//v4有2個元素,值分別是10和1
另一方面,如果初始化使用了花括號的形式但是提供的值又不能用來列表初始化
vectorv5;//列表初始化,v5有1個元素
vectorv6("hi");//錯誤,不能用字串字面值來構建vector物件,即沒有提供數量
vectorv7;//提供的值補鞥能用來列表初始化,所以是值初始化,v7有10個預設初始化的元素
vectorv8;//不能列表初始化,v8有10個值為"hi」的元素
但一般使用vector都是預設初始化後,再用成員函式push_back新增元素。 C 直接初始化和複製初始化
在c 裡,物件初始化是乙個非常重要但又容易令人混淆的問題。這裡是自己的一些總結。一。初始化與賦值的含義 初始化 包括建立 或說定義 物件並且賦給初值。如果乙個物件只被建立而沒有被初始化,則該變數只能用於被賦值 賦值 擦除物件的當前值並用新值代替。二。內建型別 一 直接初始化 1.空初始化 即無引數無...
c 直接初始化與拷貝初始化
我們常見的幾種初始化的形式 string str1 first 拷貝初始化,編譯器允許把這句話改寫為string str first 但是string類必須有public的拷貝 移動 建構函式 string str2 10,a 直接初始化 string str3 str2 直接初始化 string ...
初始化 指定初始化
id alloc 物件的誕生過程,主要是從作業系統獲得一塊足夠大的記憶體,以存放該類的全部例項變數,並將其指定為存放記憶體物件的實力變數的位置。alloc方法同時將這塊記憶體全部設定為0。結果是 bool變數初始化為no,所有的int型別變數為0,float變數為0.0,所有的指標為nil.obje...