關於局部域
如果在全局域中聲明瞭變量low,那在嵌套局部域中使用的low 仍然指向局部的low 的聲明 全局聲明會被局部聲明隱藏起來
關於全局域
程序中用到的全局對象也必須有一個定義。全局對象和非inline全局函數在一個程序內只能被定義一次,而只要給出的定義完全相同即可。inline 函數可以在一個程序中被定義多次 這要求全局對象和函數或者只有一個定義,或者在一個程序中有多個完全相同的定義。這樣的要求被稱爲一次定義法則 ODR [one definition rule]
空懸指針[dangling pointer]
當一個自動變量的地址被存儲在一個生命期長於它的指針時,該指針被稱爲空懸指針[dangling pointer]
#include "Matrix.h"
Matrix* trouble( Matrix *pm )
{
Matrix res;
// 用 pm做一些事情
// 把結果賦值給 res
return &res; // 糟糕 !
}
int main()
{
Matrix m1;
// ...
Matrix *mainResult = trouble( &m1 );
// ...
}
寄存器自動對象
函數中頻繁被使用的自動變量可以用register 聲明,如果可能的話,編譯器會把該對象裝載到機器的寄存器中。如果不能夠的話 則對象仍位於內存中,出現在循環語句中的數組索引和指針是寄存器對象的很好例子如果所選擇的變量被頻繁使用,則寄存器變量可以提高函數的執行速度。關鍵字register對編譯器來說只是一個建議,有些編譯器可能忽略該建議。而是使用寄存器分配算法找出最合適的候選放到機器可用的寄存器中,因爲編譯器知道運行該程序的機器的結構,所以它選擇寄存器的內容時常常會做出更有意義的決定 。
靜態局部變量
static 靜態局部對象具有靜態存儲持續期間[static storage duration]或靜態範圍[static extent]。雖然它的值在函數調用之間保持有效,但是其名字的可視性仍限制在其局部域內,靜態局部對象在程序執行到該對象的聲明處時被首次初始化
#include <iostream>
int traceGcd( int v1, int v2 )
{
static int depth = 1;
cout << "depth #" << depth++ << endl;
if ( v2 == 0 ) {
depth = 1;
return v1;
}
return traceGcd( v2, v1%v2 );
}
與靜態局部對象depth 相關聯的值在traceGcd()的調用之間保持有效
初始化只在traceGcd()首次被調用時執行一次 下面的小程序使用了traceGcd() #include <iostream>
extern int traceGcd(int, int);
int main() {
int rslt = traceGcd( 15, 123 );
cout << "gcd of (15,123): " << rslt << endl;
return 0;
}
編譯並運行該程序 產生下列輸出 depth #1
depth #2
depth #3
depth #4
gcd of (15,123): 3
關於auto_ptr
auto_ptr 是C++標準庫提供的類模板,它可以幫助程序員自動管理用new 表達式動態分配的單個對象(不幸的是 對用new 表達式分配的數組管理沒有類似的支持 我們不能用auto_ptr 存儲數組 如果這樣做了 結果將是未定義的
auto_ptr< int > pi( new int( 1024 ) );
if ( *pi != 1024 )
// 喔, 出錯了
else *pi *= 2;
auto_ptr 類模板背後的主要動機是支持與普通指針類型相同的語法,但是爲auto_ptr 對象所指對象的釋放提供自動管理。根據一般的常識,你可能會認爲這種額外的安全性一定來自於執行效率的開銷,但實際情況並不是這樣。因爲對這些操作的支持都是內聯的,它們由編譯器在調用點上展開,所以使用auto_ptr 對象並不比直接使用指針代價更高。
不能夠在auto_ptr 對象被定義之後 再用new 表達式創建對象的地址來直接向其賦值,而是應該使用reset
pi.reset( new int( 1024 ) );
release()操作允許將一個auto_ptr 對象的底層對象初始化或賦位給第二個對象 而不會使兩個auto_ptr 對象同時擁有同一對象的所有權 release()不僅像get()操作一樣返回底層對象的地址 而且還釋放這對象的所有權 前面代碼段可被正確改寫如下
// ok: 兩個對象仍然指向同一個對象
// 但是, pstr_auto 不再擁有擁有權
auto_ptr< string >
pstr_auto2( pstr_auto.release() );