函式
函式基礎
- 除了函式名,函式指標也可以使用運算子()運行函式
- 函式的型別指的是 ( 回傳型別 + 形參型別 )
- 存在于陳述句塊中的物件叫自動物件
- 在函式里面的物件叫區域物件,定義時不給初值就執行默認初始化(內置型別其值是未定義的,使用會報錯,不用會警告)
- 區域物件定義時加個
static就成區域靜態變數了,不給初始值會執行值初始化(內置型別默認為0) - 函式的宣告又叫函式原型
引數傳遞
-
傳實參不用型別一模一樣,能轉換就行
-
可以傳遞陣列(傳的是首元素指標,所以形參的大小寫不寫無所謂)或函式(會轉換為函式指標)
-
陣列的參考作為形參,則必須指定大小了,而且傳的時候也不能亂傳了
-
有的型別不支持拷貝(比如IO),也就不能傳值,所以只能傳參考
-
對于形參為
const的情況,實參不const也行,但是函式里就別想改值了 -
對于形參為
const參考的情況,使用參考只是為了避免拷貝的開銷,仍然不可以更改值 -
如果指標是底層
const的也就是它是指向const值的指標,那么則不可以通過指標的方式來改,但是實際上是可以改的 -
非
const的參考或指標形參會導致可接受引數范圍的縮小,因為編譯器不允許將真的不能改的東西傳到可以改的地方 -
處理不同數量實參,如果型別相同,可以使用
initializer_list做形參,型別不同的話則需要寫一個可變引數模板 -
initializer_list里的值都是const,并且拷貝賦值操作并不是真的拷貝而是共用,相當于一個vector,有size,也有begin和end(不是迭代器而是指標),傳實參的時候,實參要用大括號括起來 -
...也可以用來處理不同數量實參,但一般跟C用,C++中的類傳到這種形參一般都拷貝的不對
回傳型別
- 不可以回傳陣列或函式,必須回傳陣列或函式的指標或參考
- 回傳
void的函式如果回傳一個回傳void的函式沒問題,要是其他值則不行 - 回傳的值只要能隱式轉換成函式回傳型別就行
- 回傳區域物件的參考或指標很不好,因為函式結束后,這個物件就沒了
- 回傳參考型別那么結果就是左值
cstdib中的EXIT_SUCCESS和EXIT_FAILURE是預處理變數,與機器無關- 回傳型別是陣列指標的時候,不能在宣告中忘了維度,維度放在引數串列后面
- C++11還能回傳{}表示的串列,屬于騷操作
- 回傳型別太復雜還不想用
typedef或者using簡化的話 就用尾置回傳,也屬于騷操作
函式多載
- 需要注意的是頂層
const引數的const會被忽略,所以有無頂層const的兩個函式不能算多載,而算重復定義 - 有無底層
const可以算多載,因為確實這樣更嚴格 - 多載函式的匹配對于實參有優先級的,具體的可以參考書籍,大體規則是精確>
const>型別提升>型別轉換>型別別轉換
函式指標
- 函式指標指向函式,要求形參和回傳型別精確匹配(一模一樣,unsigned 和int都不行),加不加&無所謂
- 當賦予函式指標
nullptr或者0時,表示目前不指向任何函式,而不是代表沒有型別 - 函式指標可以作為函式的形參,直接寫函式名會自動轉為指標
- 函式指標也能作為回傳值,但是回傳的時候必須顯式指出是指標,這回編譯器不給自動轉換了
- 可以使用尾置回傳型別來表示回傳函式指標,屬于騷操作
默認實參
- 一個作用域中一個形參只能定義一次默認實參,每次宣告都可以賦予一個新的沒有默認實參的形參,但要保證默認實參都在后面
- 區域變數當不了默認實參,可以轉換為合適型別的運算式可以
行內函式
- 說白了就是讓編譯器更快處理,回傳型別前加
inline就行了,到底聯不聯交給編譯器決定 - 行內函式可以手動定義多次,因為不手動編譯器自己也做了好多次這種定義(因為就是在指定位置替換定義),所以編譯器對行內函式比較寬容,但很顯然這些定義必須都是一樣的,因此最好放在頭檔案中,
constexpr因為是行內函式所以也要遵守這個規則
constexpr函式
- 回傳型別和形參都是字面值型別,而且只有一條
return(這樣才能保證編譯時知道結果),那么這種函式就可以賦給constexpr運算式,因為這都是編譯時候干的事,所以constexpr默認設定為行內的 - 如果不加
constexpr那么函式就算生成常量運算式也不會回傳常量運算式,因為普通函式就是要運行才知道結果 - 但是加了
constexpr函式可不一定回傳常量運算式,當傳遞非常量,編譯時就計算不出值了,也就回傳非常量運算式了
assert預處理宏
- 定義在
cassert頭檔案中,其實也是預處理變數,像一個行內函式,assert(運算式)對運算式求值,一旦為假,就終止程式,真的話就啥也不做,assert干不干活依賴的是NDEBUG這個預處理變數的狀態,如果定義了就啥也不做,默認是沒定義的 assert可不是語法糖,因為只要定義NDEBUG,就真的不干活了,程式就可能會出問題,它只是用來做正式發布后就不做的除錯- 可以使用
NDEBUG和#ifndef和#endif來創建除錯的代碼,在命令列輸入-D NDEBUG則之間的代碼就不運行了 - C++編譯器提供了
__func__靜態區域變數來輸出當前函式的名字,__FILE__,__LINE__,__TIME__,__DATE__分別表示檔案名,行數,編譯時間,日期,用來為除錯輸出資訊
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/285509.html
標籤:C++
