1.函數
- C++的函數返回值類型可以是除數組外的其他任何類型;
- C++的參數列表中,方括號指出的參數其實並不是數組,而是指針。
int sum_arr(int arr[], int n);
2.函數指針
- 函數指針的聲明
// 一般聲明
double pam(int);
double (*pf)(int);
pf = pam;
// 聲明指針數組
double (*pf[3])(int) = {pam1, pam2, pam3}; //pam1,pam2,pam3 are three functions with same features
// auto聲明指針數組
auto pa = pf;
// typedef進行聲明
typedef double (*p_fun)(int);
p_fun pf = pam;
p_fun pf[5];
- 函數指針的調用,函數指針可以通過*解除引用調用,也可以像函數名一樣直接調用;
double pam(int);
double (*pf)(int);
pf = pam;
double x = (*pf)(5);
double x = pf(5); // this is the same to the code above.
3.內聯函數
- inline 內聯函數通過直接用函數代碼替換函數調用,提高了程序的運行速度;
- 代碼簡短、非遞歸的函數建議使用inline;
- 內聯函數與宏
宏是通過文本替換來實現,不能按值傳遞,而內聯函數可以。
#define SQUARE(x) ((x)*(x)) // SQUARE(c++) = (c++)*(c++), 調用後C將遞增兩次,而如果定義爲內聯函數,則c將先計算值,再遞增一次
4.引用變量
- 引用是已定義的變量的別名,使用引用做形參,調用時將直接使用原始數據,不使用副本;
- 數據量大時,使用引用可以大大節省內存空間。
- &:左值引用,&&:右值引用。
- 對於傳遞的值而不做修改的函數
如果數據對象很小,則按值傳遞;
如果數據對象數組,則只能使用指針,通常使用指向const的指針;
如果數據對象很大,則使用const指針或const引用;
如果數據對象是類對象,則使用const引用。
- 對於修改調用函數中數據的函數
如果數據對象是內置數據類型或數組,則使用指針;
如果數據對象是結構,則使用指針或引用;
如果數據對象是類對象,則使用引用。
5.儘量使用const
- const 可以避免由於無意間修改數據而導致的編程錯誤;
- const形參可以處理const和非const實參,非const形參只能處理非const數據;
- 使用const引用可以避免原始數據被修改。
6.默認參數
- 對於帶參數列表的函數,必須從右向左添加默認值。
- 對某個默認參數時,需爲參數右邊的所有參數提供默認值。
int harpo(int n, int m = 4, int j =5); // valid
int chico(int n, int m = 4, int j); // not valid
beeps = harpo(1); // valid
beeps = harpo(1,,6);// not valid
beeps = harpo(1,2,6); //valid
7.函數重載的特徵標必須不同--參數列表不同。
8.函數模板
- 格式,老的格式用class,新的格式用typenam,c++11都兼容兩種格式
template <typename T>
- 具體化優先常規模塊,而非模板函數優先具體化和常規模板
//非模板
void Swap(job &, job &);
//常規模板
template <typename T>;
void Swap(T &, T &);
//顯式具體化
template <> void Swap<job>(job &, job &);
template <> void Swap(job &, job &);//job可省略
//顯示實例化
template void Swap<int>(int, int); // ---實例化即爲直接調用
- 關鍵字decltype
//用於執行語句
decltype(x) y; //make the same type as x
//用於返回值
auto h(int x, float y) ->double; //return type is double
template<typename T1, typename T2>
auto gt(T1, T2) -> decltype(x + y) { //return type is the same to (x + y)
return x + y;
}
9.存儲持續性、作用於和鏈接性
- 局部變量: 存儲於棧中,LIFO(後進先出),函數或代碼塊創建到釋放期間持續,作用域爲該函數或代碼塊內;
- 靜態存儲持續性:程序運行過程中均存在;全局變量作用域爲所有文件,static定義於文件內,代碼塊外時,作用域爲當前文件,static定義於代碼塊內時,作用域爲當前代碼塊;
- 線程存儲持續性:通過thread_local聲明,該線程持續;
- 動態持續性:存儲於堆中,new-delete期間持續。
10.static說明符
- 變量持續性:變量將在整個程序運行過程持續,其值能被持續更改;
- 作用域:限定變量作用域爲當前文件或當前代碼塊。
11.mutable說明符:當結構或類變量爲const時,其某個成員也可以被修改。
struct data {
char name[30];
mutable int accesses; //accesses can be modified
}
const data veep = {"hello world",0};
veep.accesses = 1; //allowed
12.volatile 限定符:變量直接從內存地址取值,不進行緩存,防止被優化。
13.new作爲定位運算符時,可以將變量地址創建到指定地址中。
struct chaff {
char dross[20];
int slag;
};
char buffer[100];
int *p1 = new (buffer) chaff; //place structure in buffer
int *p1 = new (buffer) int[20]; //place int array in buffer
14.名稱空間
- 名稱空間可以是全局的,也可以位於另一個名稱空間中,但不能位於代碼塊中;
- using聲明由被限定的名稱和關鍵字using組成,using編譯指令則通過namespace,被限定的名稱和關鍵字using 組成。using 聲明導入名稱空間中部分成員變量或函數,而using編譯指令則導入名稱空間中所有成員;
namespace Jill { // create namespace Jill
double pail;
double fetch;
int pal;
struct Well { ...};
}
namespace Jill { // add goose into namespace Jill
char * goose(const char *);
}
int para = 1;
using namespace Jill; // using compile code
using Jill::fetch; //using declaration
::para = 2; //global parameter.
- 原則:使用已命名的名稱空間中的變量,而不是使用外部全局變量;
- 原則:使用已命名的名稱空間中的變量,而不是使用靜態全局變量;
- 原則:不要在頭文件中使用using編譯指令;
- 原則:導入名稱時,首選使用作用域解析運算符或using聲明的方法。