1. 程式人生 > >C++查缺補漏之變數

C++查缺補漏之變數

什麼是變數?

我們在日常程式設計中經常會有int a=10;,那麼這個a就是變數。變數提供了程式可以操作的有名字的儲存區,要是在彙編時代,我們是直接操作暫存器和記憶體地址的,那麼現在就把底層的暫存器和記憶體地址抽象出來,取了一個別名,通過這個別名也可以操作這塊記憶體。

C++中每一個兩邊都要有一個特定的型別,該型別決定了變數的大小和佈局,能夠儲存於該記憶體中的值的取值範圍,以及可以在該變數上進行的一些操作。C++中經常把變數稱為“變數”或“物件”。

什麼是物件?

什麼是物件?一般而言,物件就是記憶體中具有型別的區域,也就是計算左值表示式就會產生物件。

定義物件

1.變數初始化

在C++中變數的初始化一般分為直接初始化

複製初始化:

  • 直接初始化:用'()'號來實現:int a(10);
  • 複製初始化:用'='號來實現:int a =10;

注意事項:在C++裡面初始化並非賦值,首先初始化是值建立變數並賦值,而賦值指的是變數之前就存在,只不過是擦除當前物件的值並賦予新值。

比如下面的:

int a=10;//複製初始化
<span style="font-family:Comic Sans MS;">//+++++++++++++++++++++++</span>
<span style="font-family:Comic Sans MS;">int b;
b=10;//賦值,並非初始化
</span>
分清這兩者的區別對於C++程式設計尤為重要!

2.初始化多個變數

我們首先來看一個簡單的C++賦值語句:

int number = number;

這個語句是正確還是錯誤呢?

當一個定義中定義了兩個以上的變數的時候,每個變數都可能有自己的初始化式,物件的名字立即變為可見,所以可以用同一個定義中前面已定義的變數初始化後面的變數:

int number1=10,number2=number1;

那麼如果是int number = number這樣的式子呢?我們前面講過複製初始化分為兩步,第一步就是建立一個變數,第二步才是賦予新的值,我們首先建立了number這個變數,那麼number變數馬上可見,然後再用可見的number來初始化自己(雖然這樣做毫無意義,最終還是沒有初始化)。所以這個式子編譯器是不會報錯的。

變數的初始化規則

變數的初始化可以分為兩種:

  • 內建型別變數的初始化:內建型別變數是否自動初始化取決於變數定義的位置:1.函式體外定義的變數自動初始化為0。2.函式體內定義的變數補自動初始化,除了用作左值來進行賦值,為初始化的變數用作其他用途都是未定義的。注意:建議每個內建型別的物件都進行初始化,雖然這樣做不是必須的,但是會增加程式的安全性。
  • 類型別變數的初始化:如果定義某個類時沒有提供初始化式,這個類也可以自動呼叫預設建構函式(沒有任何初始化式,那麼就呼叫預設建構函式)來對其進行初始化,比如std::string類,如果沒有初始化式(std::string str;),那麼就自動呼叫預設建構函式來初始化str為空串。注意:如果使用者沒有定義任何建構函式,那麼為了滿足編譯的需要,編譯器會自動為你生成一個預設建構函式,這個預設建構函式沒有任何初始化效果,僅僅是為了滿足編譯的需要,如果使用者定義了一個或者多個建構函式,那麼系統將不會再自動生成預設建構函式,所以在你自定義建構函式的時候,最好也自定義一個預設建構函式(預設建構函式)。減少在沒有初始化式定義時(陣列,動態陣列,容器,作為一個類成員等等)的編譯出錯。(預設建構函式詳見:http://blog.csdn.net/wuliming_sc/article/details/3855270

定義和宣告

分清變數的定義和變數的宣告在後續的程式設計中也是尤為重要的

變數的定義:用於為變數分配記憶體空間,還可以為變數指定初始值。在一個程式中,變數有且只有一個定義

變數的宣告:用於向程式表明變數的型別和名字。定義也是宣告:在定義變數時我們定義了它的型別和名字。我們可以使用extern關鍵字來表明是在宣告而不是在定義。

如:

extern int a ;//宣告
int a ;//定義
extern不分配儲存空間,只能說明變數定義在程式的其他地方,比如在其他的C檔案裡面:
<span style="font-size:18px;">//example.c
int a=10;
//++++++++++++++++++
//main.c
extern int a;
main(){
    int b=a;//b=10;
}
</span>
編譯結果為:

gcc -c main.c -o main.o
cc    -c -o example.o example.c
gcc main.o example.o

沒有任何問題。

如果在宣告時有初始化式子,那麼它就可以被當做是定義!

<span style="font-family:Comic Sans MS;font-size:18px;">//example.c
int a=10;
//++++++++++++++++++
//main.c
extern int a=11;//錯誤,在連結兩個example.o 和 main.o的時候a就重定義了
main(){
    int b=a;//b=10;
}</span>
gcc -c main.c -o main.o
main.c:4:12: warning: ‘a’ initialized and declared ‘extern’ [enabled by default]
 extern int a=11 ;
            ^
cc    -c -o example.o example.c
gcc main.o example.o
example.o:(.data+0x0): `a'被多次定義
main.o:(.data+0x0):第一次在此定義
collect2: error: ld returned 1 exit status
make: *** [main] 錯誤 1