標籤:庫類 3.1 tar 實值型別 運算式 結束 引用 bool 強制
1.函數內的局部靜態對象在程式的執行路徑第一次經過對象定義語句的時候初始化,並且直到程式終止才被銷毀,在此期間即使對象所在的函數結束執行也不會對它有影響。
size_t get_count(){ static size_t count = 0; return ++count;}
2.當實參初始化形參的時候會忽略頂層const,換句話說,當形參有頂層const時,傳給它常量或者非常量都是可以的。
const int ci = 1; // ci的值不能被改變,const是頂層的int i = ci; // 當拷貝ci時, 忽略了它的頂層constvoid fun(const int i){}void fun(int i){} // 錯誤,重複定義
3.數組在做形參的時候是不允許拷貝數組的,而且數組通常會被轉換為指標。
// 以下三個聲明是等價的,編譯器只會檢查參數是否為int*void printArr(int *arr);void printArr(int arr[]);void printArr(int arr[10]);
4.如果想固定數組的大小,可以使用引用形參。
void printArr(int(&arr)[10]) {}int arr[1] = { 0 };printArr(arr); // 錯誤,arr不是長度為10的數組
5.如果函數的實參數量未知,但類型都相同,可以使用 initializer_list 類型的形參,initializer_list是一種標準庫類型,可以表示某種特定類型的值的數組。它和 vector 一樣都是模板類型,但是不可以修改它的元素。
initializer_list<int> lt = { 1, 2, 3 };
6.省略符形參應該僅僅用於C和C++通用的類型,大多數類類型的對象在傳遞給省略符形參的時候無法正確的被拷貝。而且省略符形參只能出現在形參列表的最後一個位置。
void fun(...) {}void fun1(int, ...) {} // 其中的逗號可以省略fun1(1, "test", "test2");
7.如果函數的傳回型別不是void那麼必須返回一個值,但是main函數可以例外,允許main函數沒有return也可以正常結束,編譯器將隱式的為main函數加入一個返回0的return語句。
8.main函數不可以遞迴,也不可以重載。
9.因為數組不能拷貝,所以函數不能返回數組,不過函數可以返回數組的指標或引用。
// 使用別名的方式typedef int arrT[10];using arrT = int[10];arrT* func(int i);
// 不使用別名的方式int (*func(int i))[10];
// 尾置傳回型別的方式(C++ 11)auto func(int i) -> int(*)[10];
// decltype 的方式(C++ 11)int arr[10];decltype(arr) *func(int i);
10.如果在函數內層範圍中聲明名字,它將隱藏外層範圍中聲明的同名實體。即在不同的範圍中無法重載函數名。
std::string read();void print(const string&);void print(double);void Test(){ bool read = false; // 新範圍,隱藏了外層的read std::string s = read(); // 錯誤,read是個bool值 void print(int); // 新範圍,隱藏了外層的print print("test"); // 錯誤,print(const string&)已被隱藏 print(1); // 正確 print(3.14); // 正確,調用的是print(int)}
11.constexper函數是指能用於常量運算式的函數,要遵循兩個規定,函數的傳回型別及所有形參的類型都得是字面實值型別,而且函數體中必須有且只有一條return語句
constexpr int count() { return 1; }constexpr int i = count();
12.允許constexpr函數的傳回值並非一個常量
constexpr int count() { return 1; }constexpr int total_count(std::size_t num) { return num * count(); };
但是上述的參數num如果給的不是一個常量,則編譯器會發出錯誤資訊。
13.和其他函數不一樣,內嵌函式和constexpr函數可以在程式中多次定義,但是它的多個定義必須完全一致,基於這個原因,內嵌函式和constexpr函數通常定義在標頭檔中。
14.assert的行為依賴於一個名為NDEBUG的預先處理變數的狀態,如果定義了NDEBUG,則assert什麼也不做。
15.當編譯器無法找出首選的函數時會產生二義性的錯誤,我們可以使用強制類型轉換來避免,但這不是一個好的選擇。
void pritf(int, int);void pritf(double, double);pritf(1, 3.14); // 編譯器不知道該匹配哪個函數,產生二義性錯誤
16.函數指標指向的是函數而非對象。
int get_max(int a, int b);int (*pf)(int, int); // pf指向一個函數,該函數傳回值是int(如果*pf不加括弧,函數的傳回值就是int*)// 以下兩個初始化等價pf = get_max;pf = &get_max;//以下兩個調用等價int i = pf(1, 2);int j = (*pf)(1, 2);
17.和數組類似,雖然不能定義函數類型的形參,但是形參可以是指向函數的指標。
// 以下兩個聲明等價void use_max(int a, int b, int pf(int,int));void use_max(int a, int b, int (*pf)(int, int));// 我們可以直接把函數作為實參使用,此時它會自定轉換成指標use_max(1, 2, get_max);
18.和數組類似,雖然不能返回一個函數,但是能返回指向函數類型的指標。
int get_max(int a, int b);// 使用別名using F = int(int, int);using pF = int(*)(int, int);pF f1(int); // 正確F f2(int); // 錯誤,傳回型別不會自動地轉換成指標F *f3(int); // 正確// 當然我們也能不用別名的形式直接聲明int (*f4(int))(int, int);// 使用auto或者decltypeauto f5(int) -> int(*)(int, int);decltype(get_max) *f6(int, int);
C++ Primer 筆記——函數