C++初始化的坑你也遇到過嗎?

2021-02-14 CPP開發者

談及C++的初始化,我們都知道要在變量定義的時候給它賦初值。確實,在每次定義的時候就初始化不僅可以避免髒數據產生,還能增加代碼的可讀性。但是,你知道這其中有多少陷阱嗎?

陷阱1:默認初始化的坑

請看一下代碼,你能知道哪些變量的值是確定的?

int a;void func(){    int b;    static int c;    cout<<"a: "<<a<<", b :"<<b<<", c :"<<c<<endl;}int main(){    cout<<"main a: "<<a<<endl;    func();    return 0;}

列印結果是:

main a: 0a: 0, b :32694, c :0

可以看到,三個變量都沒有顯式初始化,但a,c都被賦予了默認值,而b是不確定的值。

其實我們可以從《C++Primer》中找到答案:「定義於任何函數體之外的變量被初始化為0,定義於函數體內部的內置類型變量將不被初始化」。所謂定義於函數體之外的變量,其實就是全局變量,這裡拓展說一下:

初始化過的全局變量,由編譯器將其保存於靜態存儲區的data段,並且這樣的值越多,程序就越大,作業系統會在程序啟動時,將全局變量的值複製到data段中,即完成變量的初始化。

未初始化的全局變量,由編譯器保存於靜態存儲區的bss段,並且這樣的值不會被使程序變大,作業系統加載程序時才分配相應的內存,並將bass段清0,即完成變量的初始化。

所以,定義在函數體之外的變量,會被賦默認值。

但定義在函數中的變量,是在棧中分配的內存,屬於動態存儲區,此區作業系統不會幫助你清0,所以此處定義的值都是未定義的。

陷阱2:數組初始化的坑

int buff[10] = {0};for(int i = 0;i<10;i++){    cout<<buff[i]<<endl;}

這段代碼相信大家平時常寫,答案很明顯,都是0,但實際的原因,真的是因為{0}代表要將每個值設為0嗎?

答案是否定的,請看下面的這段代碼:

int buff_2[10] = {1};for(int i = 0;i<10;i++){    cout<<buff_2[i]<<",";}

得到的答案是:1,0,0,0,0,0,0,0,0,0,大家注意到了嗎?只有第一個值才是1,後面的全是0!

所以,這個坑其實是C++初始化列表的坑,初始化列表的定義中說明,如果初始化列表的數量比定義的數量少,那麼未被定義到的值將會被賦予默認值!

陷阱3:memset的坑

char buff[10];memset(buff,0,sizeof(buff));for(int i = 0;i<10;i++){    printf("%d ",buff[i]);}

大家一定會覺得這段代碼很簡單,沒錯,列印結果就是都為0,的確很簡單,但是,看下接下來的代碼:

int buff_2[10];memset(buff_2,1,sizeof(buff_2));  for(int i = 0;i<10;i++){    printf("%d ",buff_2[i]);}

是的,變量的類型變了,列印的結果是:

16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009 16843009

是不是覺得很奇怪,接下來,我們把這句:

改為:

printf("0X%x ",buff_2[i]);

得到的結果是:

0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101 0X1010101

是不是感覺很蹊蹺?

首先,在我的設備上,int是4位元組,所以buff_2總共40位元組,memset會對40個1位元組賦值0X01,而不是對10個4位元組賦值0X01。所以不要用memset對非字符型數組賦初值!

關於C++初始化的坑,你遇到過哪些?歡迎在評論中和我探討。覺得文章不錯,請點讚和在看支持我繼續分享好文。謝謝!

點讚和在看就是最大的支持❤️

相關焦點

  • 【C++札記】C++的直接初始化與複製初始化
    p=241C++中的直接初始化指的是直接調用類的構造函數進行初始化,例如:複製初始化指的是用「=」號來初始化對象,例如:根據C++的標準,直接初始化就是直接調用類的構造函數來初始化對象,例如在string a(「hello」)中,string類的string(const char *)構造函數會被調用,a被直接初始化。然而根據標準,複製初始化應該是先調用對應的構造函數創建一個臨時對象,再調用拷貝構造函數將臨時對象拷貝給要創建的對象。
  • C++機器學習庫介紹
    C++是我學習過的第一種程式語言,我喜歡在機器學習中使用它。我在之前寫過關於構建機器學習模型的文章。我收到了一個回復,問我C++有沒有機器學習的庫?這是個公平的問題。像Python和R這樣的語言有大量的包和庫來滿足不同的機器學習任務。那麼C++有沒有這樣的產品呢?是的,是的!
  • C++ 列表初始化詳解
    ,因此C++11中為了統一初始化方式,提出了列表初始化(list-initialization)的概念。,它的初始化還是遵循以往的靜態成員的額初始化方式。,是可以直接進行初始化的,對於一個類來說如果它的非靜態數據成員使用了=或者{}在聲明同時進行了初始化,那麼它就不再是聚合類型了,不適合使用列表初始化方法了。
  • 「最佳實踐」C++陷阱與套路
    ## 2.坑中坑:std::sort()相信工作5年以上至少50%的C/C++程式設計師都被它坑過,我已經聽到過了無數個悲傷的故事,《聖鬥士星矢》,《仙劍》,還有別人家的項目《天天愛消除》,都有人掉坑,程序運行幾天莫名奇妙的Crash掉,一臉懵逼。
  • C++機器學習庫介紹 | 文末送書
    C++是我學習過的第一種程式語言,我喜歡在機器學習中使用它。我在之前寫過關於構建機器學習模型的文章,我收到了一個回復,問我C++有沒有機器學習的庫?這是個很好的問題。像Python和R這樣的語言有大量的包和庫來滿足不同的機器學習任務,那麼C++有沒有這樣的產品呢?是的!在本文中,我將重點介紹兩個這樣的C++庫,我們也將看到它們都是可以運行。
  • C++ 的門門道道 | 技術頭條 - CSDN
    二、編譯器為什麼不給局部變量和成員變量做默認初始化?因為效率,C++被設計為系統級的程式語言,效率是優先考慮的方向,c++秉持的一個設計哲學是不為不必要的操作付出任何額外的代價,所以它有別於java,不給成員變量和局部變量做默認初始化,如果需要賦初值,那就由程式設計師自己去保證。
  • 買金器,黃金一口價你遇到過嗎?到底有沒有被坑呢
    買金器,黃金一口價你遇到過嗎?到底有沒有被坑呢 2020-12-05 01:04 來源:珠精姐妹花
  • 德化一網友超市購買盒裝水果被坑!你遇到過嗎?
    買盒裝草莓被坑,你遇到過嗎? 德化網友「戰狼8756」發帖附圖爆料:在城東一家超市買了一盒草莓,在購買前,超市工作人員就已用塑料盒和保鮮膜包裝好了。
  • 兄弟,你遇到過這些神坑隊友嗎?
    兄弟,你遇到過這些神坑隊友嗎? 遊戲遇到豬隊友大不了卸載遊戲 生活中遇到坑貨 只能氣到內傷還無法還手
  • python+C、C++混合編程的應用
    有的語言專注於簡單高效,比如python,內建的list,dict結構比c/c++易用太多,但同樣為了安全、易用,語言也犧牲了部分性能。在有些領域,比如通信,性能很關鍵,但並不意味這個領域的coder只能苦苦掙扎於c/c++的陷阱中,比如可以使用多種語言混合編程。
  • c++11新特性,所有知識點都在這了!
    c++11新特性吧,你是怎麼回答的呢?這裡的詳細介紹請看:左值引用、右值引用、移動語義、完美轉發,你知道的不知道的都在這裡列表初始化在C++11中可以直接在變量名後面加上初始化列表來進行對象的初始化,詳細介紹一定要看這篇文章:學會C++11列表初始化std::function &
  • C 語言會比 C++ 快?
    首先不使用 unordered_set我們基準測試的先前版本的秘密就在於 unordered_set 從來沒有在那個版本中存在過。雖然 meshoptimizer 最初使用的是 STL 容器和算法,但它從未使用過 std::unordered_set。
  • C++ | 虛函數簡介
    本文將簡單探究一下 c++ 中的虛函數實現機制。本文主要基於 vs2013 生成的 32 位代碼進行研究,相信其它編譯器(比如,gcc)的實現大同小異。先從對象大小開始 假設我們有如下代碼,假設 int 佔 4 字節,指針佔 4 字節。
  • 教科書級別的英語「坑」你遇到過多少?
    今天瓜瓜來帶大家品一品那些年被英語教科書「坑」過的表達如果有一個人和你打招呼說,How are you? 相信大家第一時間就會想到教科書中的洗腦回答,I’m fine, thank you! And you? but...I’m fine.
  • C 2 C++進階篇(1)
    首先談談筆者的水平,只學過c和數據結構,接觸過指針,對於取地址&從來沒有接觸過(因為據說是老師說不符合嚴謹的c....), python
  • 還不懂c++vector的用法,你憑什麼勇氣來的!
    今天給大家帶來一篇c++vector的介紹,難以置信這篇文章寫了我三天,不過總算整理完畢,現在分享給大家。模板類vector 和 array是數組的替代品。模板類vector 類似於string類,也是一種動態數組。 在 c++ 中,vector 是一個十分有用的容器。
  • C++ initializer_list 詳解
    template< class T >class initializer_list;要介紹initializer_list的使用,有必要先談一談列表初始化。C++11擴大了初始化列表的適用範圍,使其可用於所有內置類型和用戶定義的類型。
  • 盤點跟團遊經常會遇到的「坑」,你中過幾個?
    隨著旅遊業的急速發展,旅遊亂象也層出不窮,要想有完美的旅遊體驗,就要學會避「坑」,下面我們來說一下在旅行的過程中最容易遇到那些「坑」。二、進店購物套路多上文我有提到,沒有一個旅行團不會進店購物,但是有的團在你報名前承諾不進店不購物,這是真的嗎?
  • 一文帶你了解c++和c中字符串的使用
    ,但是如果你對c語言理解不是很深的話,那你可能就不能"享受"到這裡面的"美味"用法了,既然標題都標註了這個,我也不賣關子,下面會有總結分享的。說完了c,那麼對於我們的c++來說,它定義字符串就簡單多了,因為有關鍵字來定義,你一看就知道。那麼下面大家就隨著我的筆步一起來看看究竟吧!
  • C++打怪 之 vector
    場景實例在C語言編程中,涉及到聲明一個全局數組的時候,經常會遇到一種情況,數組的大小設定多少合適。一般情況下我們會設定一個比較大的值,例如1000甚至更大,主要就是怕在代碼運行中,用到該數組時,若數組容量不夠,出現越界的情況,從而導致宕機等較為嚴重的問題。