深入認識物件初始化

2021-04-02 14:07:50 字數 1384 閱讀 2511

來自實際專案的一段**,簡化形式如下:

switch (t)

有什麼問題嗎?似乎沒有。請用編譯器編譯一下……

嗯?!乙個錯誤「error c2361: initialization of 'a' is skipped by 'default' label」。這怎麼可能?

幾番思琢,悟出解釋:c++約定,在塊語句中,物件的作用域從物件的宣告語句開始直到塊語句的結束,也就是說default標號後的語句是可以使用物件a的。如果程式執行時從switch處跳到default處,就會導致物件a沒有被正確地初始化。確保物件的初始化可是c++的重要設計哲學,所以編譯器會很嚴格地檢查這種違例情況,像上述的示例**中default語句後面並沒有使用a,但考慮到以後**的改動可能無意中使用,所以一樣被**。

明白了原因,解決起來就很容易了。只要明確地限制物件a的作用域就行了。

switch (t)

//added for fix problem

default:

break;

}如果確實需要在整個switch語句中使用物件a,那就把int a = 0;移到switch語句之前即可。不過從原先的語句看,其意圖似乎並不是這樣的,所以推薦前面的解決方案。

結束了嗎?沒有。讓我們繼續考究錯誤提示資訊中「initialization」(也就是初始化)的確切含義。c++很看重初始化,所以往往會給我們造成一種錯覺,似乎物件在定義處一定會經過初始化過程。真實情況如何呢?還是用例項來證明吧。

switch (t)

編譯,這次沒有報錯。很明顯int a;定義了物件,但沒有進行初始化,否則就應該報告原先的錯誤。

再看看使用者自定義型別。

class b

;switch (t)

編譯結果也沒有錯誤,所以沒有提供構造器的類仍然沒有初始化過程。

如果給類加入構造器,情況就不同了。

class b

//added for initialization

};這樣就能重現原先的錯誤。證明有了構造器,編譯器就將進行初始化處理並對之進行安全檢查。

從上面的實驗,可以直觀地體驗到一些基本的c++觀念和原理,並提高認識深度。

1.int a = 0;既是宣告也是定義,還包括初始化;int a;是宣告還是定義依上下文而定,但如果是定義就不會包括初始化;a = 0;僅僅是賦值語句,在此句前物件已經存在了。

2.為了避免不必要的開銷,預設情況下,即程式設計師沒有在**中明確指示時,編譯器不提供初始化過程。某些需要確保初始化的類,請提供構造器。這裡透露出乙個c++的設計哲學:通常你會面對多種選擇,所以請精確地控制**,其收益則是可以自由取捨調配的安全性、速度、記憶體開銷等程式特性。

3.嚴密注意程式中標號的使用情況,特別是case、default等常規標號,否則他們可能會破壞物件的正確狀態。如果提供了物件初始化,則能夠獲得編譯器的額外幫助。

物件初始化

在oc中使用alloc後,會分配到一塊記憶體塊,同時這塊記憶體塊會被清零,所以初始化函式init是不需要再做置零的操作的。在oc中,應該在alloc後就呼叫初始化函式init,使用new可以達到這個效果,但new不是oc的風格。物件在init時,應該先使用其父類的init,然後再使用自己的init行...

物件初始化

我們知道當使用new關鍵字建立乙個物件的時候,會呼叫相應的建構函式對該物件進行初始化,那麼這個過程中到底都還有什麼事情呢?先看一段 當執行語句 student stu new student zhangsan 17 執行該語句的時候在記憶體中程式都做了什麼事情,讓我們一一枚舉出來 1 因為new用到...

物件初始化

每乙個物件都應該在建立之時就有確定的內容,否則就失去了物件的意義了。定義乙個物件,在系統為其分配記憶體時,應該同時對有關的資料成員賦初始值。首先,不能在類宣告中對資料成員初始化。因為類不是實體,而是抽象型別,不占用記憶體而無處容納資料。如果類中資料為私有或受保護的,則不能在定義物件時賦初值。time...