##沒有躲過的坑--程序中的變量未初始化
變量未初始化是C++編程中最為常見和易犯的錯誤之一。
但是對于全局變量,我們可以不進行初始化,這個變量會默認的用零進行初始化,但是這通常不是一個好的習慣。我們今天先不探討全局變量還是靜態全局變量。那么對于一個全部變量來說,初始化為零和不初始化(編譯器替我們初始化為零)又有什么區別嗎?
**全局變量和局部變量初始化與不初始化的區別**?
即int x 和 int x=0的區別。
int x =0; 跟 int x; 的效果看起來是一樣的。但其實這里面的差別很大,強烈建議大家所有的全局變量都要初始化,他們的主要差別如下:
編譯器在編譯的時候針對這兩種情況會產生兩種符號放在目標文件的符號表中,對于初始化的,叫強符號,未初始化的,叫弱符號。連接器在連接目標文件的時候,如果遇到兩個重名符號,會有以下處理規?
則:?
1、如果有多個重名的強符號,則報錯。?
2、如果有一個強符號,多個弱符號,則以強符號為準。?
3、如果沒有強符號,但有多個重名的弱符號,則任選一個弱符號。
例:
~~~
#include "stdafx.h"
int i;
int main(int argc, char* argv[])
{
printf(" i = %d\n",i);
int j;
printf(" j= %d\n",j);
return 0;
}
~~~
在Debug版下,i輸出是0,j輸出是-858993460,也就是0xCCCCCCCC。?
至于為什么是這個值,有網友給出這個解釋。(設計成0xcccccccc是有特殊用意的……這個好像叫做Poison,未初始化的Pointer去取值的話會出錯。肯定有人問為什么不弄成0x00000000,因為空指針是指針的有效狀態,可能會誤導人,而0xCCCCCCCC在Windows下永遠不可能是一個指針的有效狀態(不是NULL,不指向一個對象,不指向一堆對象緊接之后的區域),這就是在模擬野指針……)
值得注意的是,同樣的代碼在Release版下,這段代碼中未被初始化的變量最后打印出來的可能都是0。也有強大的網友給出解釋。(重點在于vc的一個功能:Catch release-build errors in debug build用/GZ編譯開關打開。debug版這個開關是開的,release版是關的(為了效率)。這個開關說白了就是把所有動態局部變量初始化成0xcccccccc,把所有動態堆變量初始化成0xcdcdcdcd。很多新手會忘記初始化這些本來應該初始化的變量(尤其是new出來的變量),有時他們會假定這些變量應該是0,這樣就可能出現在release版正常而debug版不正常的程序,因為release版至少局部變量的初始值很可能就是0,而有時他們又會假定或者期望這些變量不是0,這樣就帶了一個最難發現的bug)
上面的內容出自:?
[http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386](http://www.kingofcoders.com/viewNews.php?type=newsCpp&id=189&number=4836955386)
================================================
在C++中,為變量所分配的內存空間并不是完全“干凈的”,也不會在分配空間時自動做清零處理。其結果就是,一個未初始化的變量將包含某個值,但沒辦法準確地知道這個值是多少。此外,每次執行這個程序的時候,該變量的值可能都會發生改變。這就有可能產生間歇性發作的問題,是特別難以追蹤的。看看如下的代碼片段:
~~~
if (num_value)
{}
else
{}
~~~
如果num_value是未經初始化的變量,那么if語句的判斷結果就無法確定,兩個分支都可能會執行。在一般情況下,編譯器會對未初始化的變量給予提示。下面的代碼片段在大多數編譯器上都會引發一個警告信息。
~~~
int foo()
{
int number;
return number;
}
~~~
但是,還有一些簡單的例子則不會產生警告:
~~~
void increment(int &num_value)
{
++num_value;
}
int foo()
{
int number;
increment(number);
return number;
}
~~~
以上的代碼片段可能不會產生一個警告,因為編譯器一般不會去跟蹤查看函數increment()到底有沒有對nValue賦值。
未初始化變量更常出現于類中,成員的初始化一般是通過構造函數的實現來完成的。
~~~
class Foo
{
private:
int num_value_;
public:
Foo();
int GetValue() { return num_value_; }
};
Foo::Foo()
{
// Oops, 我們忘記初始化num_value_了
}
int main()
{
Foo cFoo;
if (cFoo.GetValue() > 0)
// do something
else
// do something else
}
~~~
注意,num_value_從未初始化過。結果就是,GetValue()返回的是一個垃圾值,if語句的兩個分支都有可能會執行。
==================================================?
新手程序員通常在定義多個變量時會犯下面這種錯誤:
~~~
int nValue1, nValue2 = 5;
~~~
這里的本意是nValue1和nValue2都被初始化為5,但實際上只有nValue2被初始化了,nValue1從未被初始化過。
**切記 無論什么變量,記得初始化!!!!**
- 前言
- deprecated關鍵字
- 指針(內存泄露)
- 頭文件相互包含(Compiler error C2653: not a class or namespace name)
- 獲取一張圖片的width和height
- This function or variable may be unsafe.
- 智能指針陷阱
- wstring與string的轉換
- windows下chrome瀏覽器插件不能安裝
- 重定義關鍵字
- 正確釋放vector的內存
- 獲取設備環境HDC
- 抽象類不能實例化對象(但是你明明定義的不是抽象類)
- 重載賦值運算符的自我賦值
- 程序中的變量未初始化
- 成對使用new和delete時要采取相同的形式
- 意想不到的除數為零
- map的初始化(插入數據)
- 正則表達式截取字符串
- 捕獲窗口之外的鼠標消息(鉤子還是??)
- 類中的靜態成員變量(static or const static)
- 有if就要有else(一定成對)
- map查找結果處理
- 使用using namespace std的壞習慣
- new一個指針數組、以及創建動態二維數組
- 使用太多的全局變量
- 沒有及時break出for循環
- vector使用erase后迭代器變成野指針
- C++函數的默認參數(重新定義默認參數)
- 0xC0000005: 讀取位置 xxx時發生訪問沖突
- std::string初始化、最快速判斷字符串為空
- 你開發的軟件安裝在C盤Program Files (x86)下產生的異常