C++ 關鍵字的使用(const static explict reinterpret_cast)

1  volatile
有些變量是用volatile關鍵字聲明的。當兩個線程都要用到某一個變量且該變量的值會被改變時,應該用volatile聲明,該關鍵字的作用是防止優化編譯器把變量從內存裝入CPU寄存器中。如果變量被裝入寄存器,那麼兩個線程有可能一個使用內存中的變量,一個使用寄存器中的變量,這會造成程序的錯誤執行。 volatile的意思是讓編譯器每次操作該變量時一定要從內存中真正取出,而不是使用已經存在寄存器中的值,如下:   
  volatile   BOOL   bStop   =   FALSE;   
    
  
在一個線程中:   
  while(   !bStop   )   
  {   
    ...   
  }   
  bStop   =   FALSE;   
  return;     
    
  
在另外一個線程中,要終止上面的線程循環:   
  bStop   =   TRUE;   
  while(   bStop   );   //
等待上面的線程終止,如果bStop不使用volatile申明,那麼這個循環將是一個死循環,因爲bStop已經讀取到了寄存器中,寄存器中bStop的值永遠不會變成FALSE,加上volatile,程序在執行時,每次均從內存中讀出bStop的值,就不會死循環了。 
這個關鍵字是用來設定某個對象的存儲位置在內存中,而不是寄存器中。因爲一般的對象編譯器可能會將其的拷貝放在寄存器中用以加快指令的執行速度,例如下段代碼中:   
  ...   
  int   nMyCounter   =   0;   
  for(;   nMyCounter<100;nMyCounter++)   
  {   
  ...   
  }   
  ...   
  
在此段代碼中,nMyCounter的拷貝可能存放到某個寄存器中(循環中,對nMyCounter的測試及操作總是對此寄存器中的值進行),但是另外有又段代碼執行了這樣的操作:nMyCounter   -=   1;這個操作中,對nMyCounter的改變是對內存中的nMyCounter進行操作,於是出現了這樣一個現象:nMyCounter的改變不是同步的 

                                                                                            
2  extern
2A 
c++中,還可用來指定使用另一語言進行鏈接,這時需要與特定的轉換符一起使用。目前microsoft c/c++僅支持”c”轉換標記,來支持c編譯器鏈接。使用這種情況有兩種形式:
u       extern “c” 聲明語句
u       extern “c” { 聲明語句塊 }

2B  extern   LPDIRECTDRAW4       lpdd;  聲明lpdd,但是不分配內存,只說明他是你可以用的變量,在此程序之外其他的程序中已經聲名了他。 其實他就是防止名字衝突~  被其修飾的變量(外部變量)是靜態分配空間的,即程序開始時分配,結束時釋放
如果一個頭文件被   #include   到一個以上的源文件   裏,這個頭文件中所有的定義就會出現在每一個有關的源碼文件裏。這會使它們裏的符號被定義一次以上,從而出現連接錯誤。   
        
解決辦法就是不要在頭文件裏定義變量。你只需要在頭文件裏聲明它們然後在適當的源碼文件(應該   #include   那個頭文件的那個)裏定義它們一次。extern告訴編譯器其所聲明的符號的存在,並不會使編譯器分配貯存空間。當做一個聲明而不是做定義的時候,在聲明前放一個關鍵字“extern” 
extern
關鍵字的作用是聲明變量和函數爲外部鏈接,即該變量或函數名在其它文件中可見。用其聲明的變量或函數應該在別的文件或同一文件的其它地方定義。 
例如語句:extern int a;
    
僅僅是一個變量的聲明,其並不是在定義變量a,並未爲a分配內存空間。變量a在所有模塊中作爲一種全局變量只能被定義一次,否則會出現連接錯誤。
    通常,在模塊的頭文件中對本模塊提供給其它模塊引用的函數和全局變量以關鍵字extern聲明。例如,如果模塊B欲引用該模塊A中定義的全局變量和函數時只需包含模塊A的頭文件即可。這樣,模塊B中調用模塊A中的函數時,在編譯階段,模塊B雖然找不到該函數,但是並不會報錯;它會在連接階段中從模塊A編譯生成的目標代碼中找到此函數

3  static
靜態變量作用範圍在一個文件內,程序開始時分配空間,結束時釋放空間,默認初始化爲0,使用時可改變其值。
靜態變量或靜態函數,即只有本文件內的代碼纔可訪問它,它的名字(變量名或函數名)在其它文件中不可見。
在函數體內生成的靜態變量它的值也只能維持
int max_so_far( int curr )//求至今(本次調用)爲止最大值
{
   static int biggest; //
該變量保持着每次調用時的最新值,它的有效期等於整個程序的有效期
   if( curr > biggest )
   biggest = curr;
   return biggest;
}
c++類的成員變量被聲明爲static(稱爲靜態成員變量),意味着它爲該類的所有實例所共享,也就是說當某個類的實例修改了該靜態成員變量,其修改值爲該類的其它所有實例所見;而類的靜態成員函數也只能訪問靜態成員(變量或函數)。
類的靜態成員變量必須在聲明它的文件範圍內進行初始化才能使用,private類型的也不例外。如,               
float savingsaccount::currentrate = 0.00154;   
(注:currentrate是類savingsaccount的靜態成員變量)

4  register
  
register聲明的變量稱着寄存器變量,在可能的情況下會直接存放在機器的寄存器中;但對32位編譯器不起作用,當global optimizations(全局優化)開的時候,它會做出選擇是否放在自己的寄存器中;不過其它與register關鍵字有關的其它符號都對32位編譯器有效。

5  auto
  
它是存儲類型標識符,表明變量(自動)具有本地範圍,塊範圍的變量聲明(如for循環體內的變量聲明)默認爲auto存儲類型。

6  const
 const
所修飾的對象或變量不能被改變,修飾函數時,該函數不能改變在該函數外面聲明的變量也不能調用任何非const函數。在函數的聲明與定義時都要加上const,放在函數參數列表的最後一個括號後。
 c++中,用const聲明一個變量,意味着該變量就是一個帶類型的常量,可以代替#define,且比#define多一個類型信息,且它執行內鏈接,可放在頭文件中聲明;但在c中,其聲明則必須放在源文件(即.c文件)中,在cconst聲明一個變量,除了不能改變其值外,它仍是一具變量,如
const int maxarray = 255;
char store_char[maxarray];  //c++
中合法,c中不合法

1.如果const位於星號左側,const用來修飾指針所指向的變量,
       
即指針指向的爲不可變的.
2.
如果const位於星號右側,const就是修飾指針本身,即指針本身是
不可變的.


7 mutable關鍵字的用法 
關鍵字mutableC++中一個不常用的關鍵字,他只能用於類的非靜態和非常量數據成員
我們知道一個對象的狀態由該對象的非靜態數據成員決定,所以隨着數據成員的改變,
對像的狀態也會隨之發生變化
如果一個類的成員函數被聲明爲const類型,表示該函數不會改變對象的狀態,也就是
該函數不會修改類的非靜態數據成員.但是有些時候需要在該類函數中對類的數據成員
進行賦值.這個時候就需要用到mutable關鍵字了

mutable關鍵字提示編譯器該變量可以被類的const函數修改

8 explicit
explicit
關鍵字用於取消構造函數的隱式轉換,對有多個參數的構造函數使用explicit是個語法錯誤。


9 C++ 同時提供了四種新的強制轉型形式(通常稱爲新風格的或 C++ 風格的強制轉型):
const_cast<T>(expression)
dynamic_cast<T>(expression)
reinterpret_cast<T>(expression)
static_cast<T>(expression)
每一種適用於特定的目的:

  ·const_cast 一般用於強制消除對象的常量性。它是唯一能做到這一點的 C++ 風格的強制轉型。

  ·dynamic_cast 主要用於執行安全的向下轉型(safe downcasting,也就是說,要確定一個對象是否是一個繼承體系中的一個特定類型。它是唯一不能用舊風格語法執行的強制轉型。也是唯一可能有重大運行時代價的強制轉型。(過一會兒我再提供細節。)

  ·reinterpret_cast 是特意用於底層的強制轉型,導致實現依賴(implementation-dependent)(就是說,不可移植)的結果,例如,將一個指針轉型爲一個整數。這樣的強制轉型在底層代碼以外應該極爲罕見。在本書中我只用了一次,而且還僅僅是在討論你應該如何爲裸內存(raw memory)寫一個調諧分配者(debugging allocator)的時候。

  ·static_cast 可以被用於強制隱型轉換(例如,non-const 對象轉型爲 const 對象(就像 Item 3 中的),int 轉型爲 double,等等)。它還可以用於很多這樣的轉換的反向轉換(例如,void* 指針轉型爲有類型指針,基類指針轉型爲派生類指針),但是它不能將一個 const 對象轉型爲 non-const 對象。(只有 const_cast 能做到。)

10. C++ 是沒finally關鍵字的,通過析構函數將資源釋放掉,在C++中通常使用RAII,即Resource Aquisition Is Initialization.
就是將資源封裝成一個類,將資源的初始化封裝在構造函數裏,釋放封裝在析構函數裏。要在局部使用資源的時候,就實例化一個local object。
在拋出異常的時候,由於local object脫離了作用域,自動調用析構函數,會保證資源被釋放

throw

例如:explicit

      auto_ptr(element_type* __p = 0) throw() : _M_ptr(__p) { }

這是異常規範,只會出現在聲明函數中,表示這個函數可能拋出任何類型的異常

void GetTag() throw(int);表示只拋出int類型異常
void GetTag() throw(int,char);表示拋出in,char類型異常
void GetTag() throw();表示不會拋出任何類型異常
void GetTag() throw(...);表示拋出任何類型異常

void GetTag() throw(int);表示只拋出int類型異常
並不表示一定會拋出異常,但是一旦拋出異常只會拋出int類型,如果拋出非
int類型異常,調用unexsetpion()函數,退出程序。

假如你加一個throw()屬性到你的永遠不會拋出異常的函數中,編譯器會非常聰明的知道代碼的意圖和決定優化方式

轉自:http://www.cnblogs.com/zpsy/articles/1810402.html

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