傳值參數與傳引用參數
#include<iostream>
using namespace std;
void a(int); //傳值參數
void b(int&); //傳引用參數
int main()
{
int s = 0, t = 10;
a(s); // 1
cout << s << endl; // 0
b(t); // 10
cout << t << endl; // 10
return 0;
}
void a(int i)
{
++i;
cout << i << endl;
}
void b(int& j)
{
++j;
cout << j << endl;
}
引用傳遞的優勢:(1)可以直接操作引用形參所引的對象;(2)使用引用形參可以避免拷貝大的類類型對象或容器類型對象;(3)使用引用形參可以幫助我們從函數中返回多個值。
普通引用與常量引用(一般情況下,與普通引用相比,我們更應該選擇使用常量引用作爲參數類型)
bool is_empty(string& s) { return s.empty() ;}
//寫法缺陷:1、給使用者誤導,即允許修改變量s的內容 2、限制了函數所能接受的實參類型,
//我們無法把const對象、字面值常量或者需要進行類型轉換的對象傳給普通的引用形參。
//修改
bool is_empty(const string& s) { return s.empty(); }
關於交換兩個int指針
//值傳遞,該函數既不交換指針,也不交換指針所指的內容,所有改變都侷限於函數內部
void SwapPointer1(int *p, int *q)
{
int *temp = p;
p = q;
q = temp;
}
//值傳遞,該函數交換指針所指的內容,在函數內部通過解引用的方式直接訪問內存並修改了指針所指的內容
void SwapPointer2(int *p, int *q)
{
int temp = *p;
*p = *q;
*q = temp;
}
//參數形式爲int *&,其含義是,該參數是一個引用,引用的對象是內存中一個int指針,把指針當成對象,交換指針本身的值
//該函數和交換指針本身的值,即交換指針所指的內存地址
void SwapPointer3(int *&p, int *&q)
{
int *temp = p;
p = q;
q = temp
}
含有可變形參的函數
爲了編寫能處理不同數量實參的函數,C++11新標準提供了兩種主要的方法:如果所有的實參類型相同,可以傳遞一個名爲initializer_list的標準庫類型;如果實參的類型不同,我們可以編寫一種特殊的函數,即可變函數模板。
什麼情況下返回的引用有效?
如果引用所引的是函數開始之前就已經存在的對象,則返回該引用有效;如果引用所引是函數的局部變量,則隨着函數結束局部變量也失效了,此時返回的引用無效。
當不希望返回的對象被修改時,返回對常量的引用。
返回數組的引用或者指針
//函數聲明,使其返回數組的引用並且該數組包含10個string對象
string (&func())[10];
//使用類型別名
typedef string arr[10];
arr& func();
//使用尾置返回類型
auto func() -> string(&) [10];
//使用decltype關鍵字
string str[10];
decltype(str) &func();
關於函數重載
int calc(int, int);
int calc(const int, const int);//非法,頂層const不影響傳入參數的對象
int get();
double get();//非法,重載函數必須在形參數量或形參類型上有所區別
int *reset(int *);
double *reset(double *);//合法,重載關係,形參類型有區別
關於默認實參
int ff(int a, int b = 0, int c = 0);//聲明正確
char *init(int ht = 24, int wd, char backgrand);//錯誤
//C++規定一旦某個形參被賦予了默認實參,則它後面所有形參都必須有默認實參
調用函數,實參按照其位置解析,默認實參負責填補函數缺少的尾部實參。
關於內聯函數
內聯函數以及函數聲明都應該放在頭文件中,在普通函數前加上inline,即成內聯函數。內聯函數在編譯時展開,從而消除調用函數時產生的開銷。內聯機制適用於規模較小、流程直接、頻繁調用的函數。
constexper函數
指用於常量表達式的函數,規定函數的返回類型及所有形參類型都得是字面值類型,而且函數體中必須有且只能有一條return語句。
關於調試幫助
#include<iostream>
#include<vector>
using namespace std;
//遞歸函數輸出vector<int>的內容
void print(vector<int> vInt, unsigned index)
{
unsigned sz = vInt.size();
//設置在此處輸出調試信息
#ifndef NDEBUG
cout << "vector對象的大小是:" << sz << endl;
#endif //NDEBUG
if(!vInt.empty() && index < sz)
{
cout << vInt[index] << endl;
print(vInt, index + 1);
}
}
int main()
{
vector<int> v = {1,3,5,7,9,11,13,15};
print(v,0);
return 0;
}
關於實參類型轉換
關於函數指針
//函數指針的聲明和使用
//函數聲明
int func(int, int);
//vector對象,其爲元素指向上述函數的指針
vector<decltype(func)*> vF;
#include<iostream>
#include<vector>
using namespace std;
int func1(int a, int b)
{
return a + b;
}
int func2(int a, int b)
{
return a - b;
}
int func3(int a, int b)
{
return a * b;
}
int func4(int a, int b)
{
return a / b;
}
void Compute(int a, int b, int (*p)(int, int))
{
cout << p(a,b) << endl;
}
int main()
{
int i = 5,j = 10;
decltype(func1) *p1 = func1, *p2 = func2, *p3 = func3, *p4 = func4;
vector<decltype(func1)*> vF = {p1, p2, p3, p4};
for(auto p : vF)//遍歷vector中的每個元素,依次調用四則運算函數
{
Compute(i, j, p);
}
return 0;
}