函數
內聯(inline)函數
在c++中inline
關鍵字可以用來修飾函數,用來在編譯階段請求編譯器將函數體的代碼直接插入調用處,而不是通過函數調用的機制。
-
用途:
在頻繁調用一個函數時,由於函數調用產生的開銷是很大的,而用inline
函數實際上是用空間換取時間的方式不去堆棧上調用函數,加快調用。 -
適用函數:短小且經常調用的函數
-
優點: 效率提高
-
缺點:可能適得其反,甚至,編譯器直接不允許這麼操作
幾點說明:
- 當代編譯器可以智能的爲我們自動內聯函數。
- 我們將函數
inline
只是一種請求,不是強制,可能編譯器會否認這種inline。
函數模板
C++提供了函數模板(function template)。
函數模板實際上是建立一個通用函數,其函數類型和形參類型不具體指定,用一個虛擬的類型來代表。
定義函數模板的一般形式爲
template<typename T>
通用函數定義
或
template <class T>
template<typename T>
T myMax(T a,T b){
return a>b?a:b;
}
template<class T>
T myMin(T a,T b){
return a<b?a:b;
}
int main(){
int a = myMax(1, 5);
double b = myMin(7.5, 10.8);
cout<<a<<endl;
cout<<b<<endl;
return 0;
}
具有默認參數值的函數
在C++中定義函數時,允許給參數指定一個缺省的值。在調用函數時,若明確給出了這種實參的值,則使用相應實參的值。若沒有給出相應的實參,則使用缺省的值。
說明:
- 不可以靠左邊缺省
void fun(int x=0,int y); // error
void fun(int x,int y=0,int z); //error
- 函數原型說明時可以不加變量名
void fun(int=0,int=1,double=2.0);
- 只能給出一次缺省值
void fun(int=0,int=1);
void fun(int a=0,int b=1){cout<<a+b+c<<endl;} //error,重複定義,哪怕一樣也不可以。
注意:
void f(){cout<<"1"<<endl;}
void f(int x=0){cout<<"2"<<endl;}
int main(){
f(); //error,模糊調用
f(); //error,模糊調用
return 0;
}
作用域(scope)
作用域是指程序中所說明的標識符在哪一個區間內有效,即在哪一個區間內可以使用該標識符。
- 塊作用域
{}
具有塊作用域的標識符在其作用域內,將屏蔽包含本塊的同名標識符,即變量名相同,局部更優先。
int x = 1;
{
int x=10;
cout<<x<<endl; // 10;
}
- 函數原型作用域
在函數原型的參數表中說明的標識符所具有的作用域稱爲函數原型作用域,從其說明處開始,到函數原型說明的結束處結束
由於所說明的標識符與該函數的定義及調用無關,編譯系統對函數聲明中的變量名是忽略的,即使在調用函數時也沒有爲它們分配存儲單元。可以在函數原型說明中只作參數的類型說明,省略參量名。
int max(int,int);
- 文件作用域
在函數外定義的變量稱爲全局變量。
- 其缺省的作用範圍是:從定義全局變量的位置開始到該源程序文件結束。
int x;
int main(){
cout<<x;
cout<<y; //error,此時還未定義。
return 0;
}
int y;
-
當局部變量與全局變量同名時,局部變量優先。
-
在塊作用域內可通過作用域運算符“::”來引用與局部變量同名的全局變量。
int x = 1;
int main(){
int x = 2;
cout<<x<<endl; // 2
cout<<::x<<endl; // 1
return 0;
}
注意:
不要過多的使用全局變量(儘量不用):
-
全局變量在程序的全部執行過程中都佔用存儲單元,而不是僅在需要時纔開闢單元。
-
降低了函數的通用性。如果將一個函數移到另一個文件中,還要將有關的外部變量及其值一起移過去。但若該外部變量與其他文件的變量同名,就會出現問題,降低了程序的可靠性和通用性。一般要求把程序中的函數做成一個封閉體,只通過“實參——形參”的渠道與外界發生聯繫外,這樣的程序移植性好,可讀性強。
-
函數作用域
-
類作用域
存儲類別(storage duration)
- 靜態存儲:在程序運行期間有固定的存儲空間,直到程序運行結束。
- 動態存儲:在程序運行期間根據需要分配存儲空間,函數結束後立即釋放空間。若一個函數在程序中被調用兩次,則每次分配的單元有可能不同。
變量
全局變量
- 在函數外定義的變量稱爲全局變量。
其缺省的作用範圍是:從定義全局變量的位置開始到該源程序文件結束。
全局變量是在函數的外部定義的**,編譯時分配在靜態存儲區**,如果未賦初值,其值爲0或空字符。
- 1.
extern
關鍵字
當在一個文件中要引用另一個文件中的全局變量或在同一個文件中全局變量定義之前要引用它時,可用extern
作說明,相當於擴展全局變量的作用域。
這也就是缺省的狀態,也就是說默認就是extern
修飾的。
- 在一個文件內提前聲明全局變量
如果去掉extern
這個關鍵字,值就是亂的了
int main(){
extern int a,b;
cout<<a<<" "<<b<<endl; // 1 2
return 0;
}
int a=1,b=2;
- 在多文件的程序中聲明外部變量及調用另一個.cpp文件中的函數
// a.cpp
#include<iostream>
using namespace std;
int a;
int main(){
extern int myPower(int); // 聲明將要調用在b.cpp文件中定義的函數
int m;
cin>>a>>m;
int ans = myPower(m);
cout<<ans<<endl;
return 0;
}
// b.cpp
// 在a.cpp文件中的全局變量a的聲明
extern int a;
int myPower(int n){
int temp = 1;
for(int i=1;i<=n;i++){
temp*=a;
}
return temp;
}
- 2.
static
關鍵字
限定全局變量僅能在本文件中引用,即使在其它文件中用extern說明也不能使用。相當於限制了全局變量的作用域範圍。
static
修飾全局變量:在函數外部定義,存儲在靜態存儲區,只限在本文件中使用,與extern
對應。
局部變量
-
自動變量(
auto
):默認,存儲在動態區.auto
關鍵字可以省略。 -
靜態局部變量(
static
):-
靜態局部變量在靜態存儲區內分配存儲單元。在程序整個運行期間都不釋放。
編譯時爲靜態局部變量賦初值,只賦初值一次,在程序運行時它已有初值。以後每次調用函數時不再重新賦初值而只是保留上次函數調用結束時的值。
如果在定義局部變量時不賦初值的話,對靜態局部變量來說,編譯時自動賦初值0(對數值型變量)或空字符(對字符型變量)。 -
雖然靜態局部變量在函數調用結束後仍然存在,但其他函數不能引用它(可見性仍雖然是局部的,只是生命週期變了)。
-
如不是必需,不要用靜態局部變量 。
-
-
寄存器變量(
register
)
一般情況下,變量的值是存放在內存中的。當程序中用到哪一個變量的值時,由控制器發出指令將內存中該變量的值送到CPU中的運算器。經過運算器進行運算,如果需要存數,再從運算器將數據送到內存存放。
爲提高執行效率,C++允許將局部變量的值放在CPU中的寄存器中,需要用時直接從寄存器取出參加運算,不必再到內存中去存取。這種變量叫做寄存器變量,用關鍵字register
聲明。
注意:
在程序中定義寄存器變量對編譯系統只是建議性,不是強制性的。
現在使用的編譯系統能夠自動識別使用頻繁的變量,將這些變量放在寄存器中。編程時,不必要再使用register聲明變量,交給編譯器去自動處理。