程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> define 與 inline,defineinline

define 與 inline,defineinline

編輯:C++入門知識

define 與 inline,defineinline


#define和inline 的區別

define:定義預編譯時處理的宏
  只進行簡單的字符替換,無類型檢測

typedef:定義類型別名 用於處理復雜類型
  例: typedef int A;
  則:A a; //定義a為int

inline: 內聯函數對編譯器提出建議,是否進行宏替換,編譯器有權拒絕

  既為提出申請,不一定會成功

 static一、產生背景

引出原因:函數內部定義的變量,在程序執行到它的定義處時,編譯器為它在棧上分配空間,大家知道,函數在棧上分配的空間在此函數執行結束時會釋放掉,這樣就產生了一個問題: 如果想將函數中此變量的值保存至下一次調用時,如何實現?

最容易想到的方法是定義一個全局的變量,但定義為一個全局變量有許多缺點,最明顯的缺點是破壞了此變量的訪問范圍(使得在此函數中定義的變量,不僅僅受此函數控制)。類的靜態成員也是這個道理。
解決方案:因此C++ 中引入了static,用它來修飾變量,它能夠指示編譯
器將此變量在程序的靜態存儲區分配空間保存,這樣即實現了目的,又使得此變量的存取范圍不變。
二、具體作用
Static作用分析總結:static總是使得變量或對象的存儲形式變成靜態存儲,連接方式變成內部連接,對於局部變量(已經是內部連接了),它僅改變其存儲方式;對於全局變量(已經是靜態存儲了),它僅改變其連接類型。(1 連接方式:成為內部連接;2 存儲形式:存放在靜態全局存儲區)


const
一、產生背景
a C++有一個類型嚴格的編譯系統,這使得C++程序的錯誤在編譯階段即可發現許多,從而使得出錯率大為減少,因此,也成為了C++與C相比,有著突出優點的一個方面。
b C中很常見的預處理指令 #define VariableName VariableValue 可以很方便地進行值替代,這種值替代至少在三個方面優點突出:
一是避免了意義模糊的數字出現,使得程序語義流暢清晰,如下例:
  #define USER_NUM_MAX 107 這樣就避免了直接使用107帶來的困惑。
二是可以很方便地進行參數的調整與修改,如上例,當人數由107變為201時,改動此處即可;
三是提高了程序的執行效率,由於使用了預編譯器進行值替代,並不需要為這些常量分配存儲空間,所以執行的效率較高。然而,預處理語句雖然有以上的許多優點,但它有個比較致命的缺點,即,預處理語句僅僅只是簡單值替代,缺乏類型的檢測機制。這樣預處理語句就不能享受C++嚴格類型檢查的好處,從而可能成為引發一系列錯誤的隱患。

Const 推出的初始目的,正是為了取代預編譯指令,消除它的缺點,同時繼承它的優點。現在它的形式變成了:

Const DataType VariableName = VariableValue ;
2) 具體作用
1.const 用於指針的兩種情況分析:
     int const *A;  //A可變,*A不可變
     int *const A;  //A不可變,*A可變
 分析:const 是一個左結合的類型修飾符,它與其左側的類型修飾符和為一個
類型修飾符,所以,int const 限定 *A,不限定A。int *const 限定A,不限定*A。
2.const 限定函數的傳遞值參數:
     void Fun(const int Var);
     分析:上述寫法限定參數在函數體中不可被改變。
3.const 限定函數的值型返回值:
const int Fun1();
const MyClass Fun2();
     分析:上述寫法限定函數的返回值不可被更新,當函數返回內部的類型時(如Fun1),已經是一個數值,當然不可被賦值更新,所以,此時const無意義,最好去掉,以免困惑。當函數返回自定義的類型時(如Fun2),這個類型仍然包含可以被賦值的變量成員,所以,此時有意義。
4. 傳遞與返回地址: 此種情況最為常見,由地址變量的特點可知,適當使用const,意義昭然。
5. const 限定類的成員函數:
class ClassName {
 public:
  int Fun() const;
 .....
}
  注意:采用此種const 後置的形式是一種規定,亦為了不引起混淆。在此函數的聲明中和定義中均要使用const,因為const已經成為類型信息的一部分。
獲得能力:可以操作常量對象。
失去能力:不能修改類的數據成員,不能在函數中調用其他不是const的函數。


inline

1) 產生背景
inline這個關鍵字的引入原因和const十分相似,inline 關鍵字用來定義一個類的內聯函數,引入它的主要原因是用它替代C中
表達式形式的宏定義。
表達式形式的宏定義一例:
   #define ExpressionName(Var1,Var2) (Var1+Var2)*(Var1-Var2)
       這種表達式形式宏形式與作用跟函數類似,但它使用預編譯器,沒有堆棧,使用上比函數高效。但它只是預編譯器上符號表的簡單替換,不能進行參數有效性檢測及使用C++類的成員訪問控制。
inline 推出的目的,也正是為了取代這種表達式形式的宏定義,它消除了它的缺點,同時又很好地繼承了它的優點。inline代碼放入預編譯器符號表中,高效;它是個真正的函數,調用時有嚴格的參數檢測;它也可作為類的成員函數。
2) 具體作用
直接在class類定義中定義各函數成員,系統將他們作為內聯函數處理;成員函數是內聯函數,意味著:每個對象都有該函數一份獨立的拷貝。
在類外,如果使用關鍵字inline定義函數成員,則系統也會作為內聯函數處理;

 

內聯函數和宏的區別在於,宏是由預處理器對宏進行替代,而內聯函數是通過編譯器控制來實現的。而且內聯函數是真正的函數,只是在需要用到的時候,內聯函數像宏一樣的展開,所以取消了函數的參數壓棧,減少了調用的開銷。你可以象調用函數一樣來調用內聯函數,而不必擔心會產生於處理宏的一些問題。我們可以用Inline來定義內聯函數,不過,任何在類的說明部分定義的函數都會被自動的認為是內聯函數。

下面我們來介紹一下內聯函數的用法。


  內聯函數必須是和函數體申明在一起,才有效。像這樣的申明Inline Tablefunction(int I)是沒有效果的,編譯器只是把函數作為普通的函數申明,我們必須定義函數體。


Inline tablefunction(int I) {return I*I};


  這樣我們才算定義了一個內聯函數。我們可以把它作為一般的函數一樣調用。但是執行速度確比一般函數的執行速度要快。


  我們也可以將定義在類的外部的函數定義為內聯函數,比如:


Class TableClass{

 Private:

  Int I,j;

 Public:

  Int add() { return I+j;};

  Inline int dec() { return I-j;}

  Int GetNum();

}

inline int tableclass::GetNum(){

return I;

}


  上面申明的三個函數都是內聯函數。在C++中,在類的內部定義了函數體的函數,被默認為是內聯函數。而不管你是否有inline關鍵字。

如何告訴編譯器使一個成員函數成為內聯函數?
聲明內聯成員函數看上去和普通函數非常類似:
class Fred {public:   
void f(int i, char c);}; 
但是當你定義內聯成員函數時,在成員函數定義前加上 inline 關鍵字,並且將定義放入頭文件中:inlinevoid Fred::f(int i, char c){   // ...}通常將函數的定義({...}之間的部分)放在頭文件中是強制的。如果你將內聯函數的定義放在 .cpp 文件中並且在其他 .cpp 文件中調用它,連接器將給出“unresolved external”錯誤。

內聯函數在C++類中,應用最廣的,應該是用來定義存取函數。我們定義的類中一般會把數據成員定義成私有的或者保護的,這樣,外界就不能直接讀寫我們類成員的數據了。對於私有或者保護成員的讀寫就必須使用成員接口函數來進行。如果我們把這些讀寫成員函數定義成內聯函數的話,將會獲得比較好的效率。


Class sample{

 Private:

  Int nTest;

 Public:

  Int readtest(){ return nTest;}

 Void settest(int I) {nTest=I;}

}


  當然,內聯函數也有一定的局限性。就是函數中的執行代碼不能太多了,如果,內聯函數的函數體過大,一般的編譯器會放棄內聯方式,而采用普通的方式調用函數。這樣,內聯函數就和普通函數執行效率一樣了。


C關鍵字
#define 宏名要替換的代碼    
宏定義,保存在預編譯器的符號表中,執行高效;作為一種簡單的符號替換,不進行其中參數有效性的檢測
typedef 已有類型 新類型
別名, 常用於創建平台無關類型, typedef 在編譯時被解釋,因此讓編譯器來應付超越預處理器能力的文本替換

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved