2010-6-12

1、c++ 分配空間

    對於全局對象,靜態對象以及分配在棧區域內的對象,對它們的內存分配是在編譯階段就完成了,而對於分配在堆區域內的對象,它們的分配是在運行是動態進行的

     全局對象和靜態對象。編譯器會爲他們劃分一個獨立 的段(全局段)爲他們分配足夠的空間,一般不會涉及到內存空間不夠的問題。  ----全局對象和靜態對性不會涉及到內存空間不夠的問題

    棧區域的大小由編譯器的設置決定,不管具體的設置怎樣,總歸它是有一個具體的值,所以棧空間是有限的,  ----棧區域會涉及到內存空間不夠的問題

 

    對 象的初始化是通過初始化列表來完成,而對象的賦值則纔是通過構造函數,或者更準確的說應該是構造函 數的實現體

 

                                                                    ---《C++類對象創建過程揭密》delicious c++

 

2、const 用法:

1. const修飾參數。const只能修飾輸入參數。
   1)如果輸入參數是指針型的,用const修飾可以防止指針所指向的內容被意外修 改。
   2)如果參數採用值傳遞的方式,無需const,因爲函數自動產生臨時變量複製該參數。
   3)非內部數據類型的參數,需要臨時對象複製參數,而臨時對象的構造,析構,複製較爲費時,因此建議採用前加const的引用方式傳遞非內部數據類型。而 內部數據類型無需引用傳遞。

2.   const修飾函數返回值。
   1)函數返回const指針,表示該指針不能被改動,只能把該指針賦給const修飾的同類型指針變量。
   2)函數返回值爲值傳遞,函數會把返回值賦給外部臨時變量,用const無意義!不管是內部還是非內部數據類型。
   3)函數採用引用方式返回的場合不多,只出現在類的賦值函數中,目的是爲了實現鏈式表達。

3.   const+成員函數。任何不修改數據成員的函數都應該聲明爲const類型,如果const成員函數修改了數據成員或者調用了其他函數修改數據成員,編 譯器都將報錯!

 

幾個誤區:

【誤區1】

const int* a = &b;                 /* [1]*/
int const *a = &b;                 /* [2]*/
int* const a = &b;                 /* [3]*/
const int* const a = &b;           /* [4]*/

看看上面的4行代碼,或許可以這麼理解:

如果const位於星號的左側,則const就是用來修飾指針所指向的變 量,即指針指向爲常量;如果const位於星號的右側,const就是修飾指針本身,即指針本身是常量。因此,[1]和[2]的情況相同,都是指針所指向 的內容爲常量(const放在變量聲明符的位置無關),這種情況下不允許對內容進行更改操作,如不能*a = 3 ;[3]爲指針本身是常量,而指針所指向的內容不是常量,這種情況下不能對指針本身進行更改操作,如a++是錯誤的;[4]爲指針本身和指向的內容均爲常 量。

 

但是我想上面的解釋不一定正確. 關於const int* a = &b, 並不是說a所指向的是常量,而應該理解成: a所指向的內容不能通過*a來改變,對於a所指向的內容是不是常量並沒有限制。如下面的代碼,是可以通過編譯的。

 

    const int *p = &b;

    int *q = &b;

    *q++;

 

【誤區2】C++中的const 是具有內部鏈接的( 不同於C)

下面是摘自C++中關於鏈接的一段話:

— When a name has external linkage, the entity it denotes can be referred to by names from scopes

other translation units or from other scopes of the same translation unit.

— When a name has internal linkage, the entity it denotes can be referred to by names from other scope

the same translation unit.

—       When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.

 

A name having namespace scope (3.3.5) has internal linkage if it is the name of

— an object, reference, function or function template that is explicitly declared static or,

—  an object or reference that is explicitly declared const and neither explicitly declared extern nor

previously declared to have external linkage; or

—       a data member of an anonymous union.

從上面可以看出const對象是具有內部鏈接的

內部鏈接的意思就是:

 

/*----A.h------*/ 

int a;

const int b;

/*----test1.cc-------*/

#include “A.h”

/*----test2.cc-------*/

#include “A.h” 

 

當test1.cc 和test2.cc 鏈接的時候,a會出現變量重定義的錯誤,而b是不會的。因爲b是具有內部鏈接的變量,相當於在test1.cc和test2.cc中各有一份b的符號。

 

const變量放在頭文件中是不會引起鏈接時候的重複定義的,但是也不推 薦將const變量放在頭文件中。

const變量不是在編譯的時候進行常量摺疊,相當於宏的替 換,const變量是不佔內存的。

但是 在某一些情況下,編譯器會爲const分配內存,比如:

 

const int a = 10;

const int *p = &a;

 

當你想獲取const變量的地址時(當然你也可以將a的地址打印出來看 看),編譯器就會強制爲const變量分配內存了。所以當你在含有const變量的頭文件被多個編譯單元包含時,const變量也有可能在編譯單元中佔據 內存。所以一般是不推薦將const 或者static變量放在頭文件中。當然這樣做也無可厚非。

下面這種情況const也是會分配內存的:

 

const int a[5] = {1, 2, 3, 4, 5};

 

所以下面的語句也就自然而然是不能通過編譯的了:

 

int arr[a[2]];

 

雖然a[2]的類型也是const int,但是它與下面的這種情況是有區別的:

 

const int k = 3;

int arr[k];

 

因爲k是const 類型,在編譯的時候進行了常量摺疊。而上面的a[2]雖然也是const int型,但是它存在於內存中。數組聲明時數組的維數是不允許用內存中的數據來定義的。所以編譯器會在此報出illegal的錯誤。

當然可能不同的編譯器會有不同的編譯結果。比如在gcc下你編譯上述的代 碼會詭異的通過,但是這是不符合C++標準的。當然如果你加上參數-pedantic的話,你就會發現編譯器乖乖的聽你的話了。

 

const變量在大部分情況下是編譯時的常量,如果需要運行時的常量,應 該怎麼做呢?像下面的代碼這樣:

const int const_runtime = get_v() // get_v在其他地方定義

                                                                                                          ------ http://www.cppblog.com/xlyz/archive/2010/06/06/117256.html

 

const 總結:

    一般情況下,編譯器是不對const變量進行內存分配的,會直接進行常量摺疊,類似於宏定義。 而如果你要想取得const類型變量的地址的話,那編譯器就會爲const變量分配一個地址。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章