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所指向的內容是不是常量並沒有限制。如下面的代碼,是可以通過編譯的。
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 (
— 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------*/
const int b;
/*----test1.cc-------*/
/*----test2.cc-------*/
當test1.cc 和test2.cc 鏈接的時候,a會出現變量重定義的錯誤,而b是不會的。因爲b是具有內部鏈接的變量,相當於在test1.cc和test2.cc中各有一份b的符號。
const變量放在頭文件中是不會引起鏈接時候的重複定義的,但是也不推 薦將const變量放在頭文件中。
const變量不是在編譯的時候進行常量摺疊,相當於宏的替 換,const變量是不佔內存的。
但是 在某一些情況下,編譯器會爲const分配內存,比如:
const int *p = &a;
當你想獲取const變量的地址時(當然你也可以將a的地址打印出來看 看),編譯器就會強制爲const變量分配內存了。所以當你在含有const變量的頭文件被多個編譯單元包含時,const變量也有可能在編譯單元中佔據 內存。所以一般是不推薦將const 或者static變量放在頭文件中。當然這樣做也無可厚非。
下面這種情況const也是會分配內存的:
所以下面的語句也就自然而然是不能通過編譯的了:
雖然a[2]的類型也是const int,但是它與下面的這種情況是有區別的:
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變量分配一個地址。