C++11中的可變參數函數與模板

所謂可變參數指的是函數的參數個數可變,參數類型不定的函數。

省略符表達可變參數

函數可以用省略符形參”…”表示不定參數部分,省略符形參只能出現在形參列表的最後一個位置,這是從C語言繼承過來的表達方式。它的形式如下:

void foo(parm_list, ...);

int printf(const char* format, ...);

下面是< cstdarg >頭文件中的幾個宏定義

C/C++11中的可變參數函數與模板

舉個例子:

C/C++11中的可變參數函數與模板

這種方式有什麼問題呢?

1. 函數本身並不知道傳進來參數個數,多傳一個參數,或者少傳一個參數,在編譯期是檢測不到這個問題的,這就可能會導致未定義的錯誤。

2. 函數不知道傳進來的參數類型。如果函數類型與預期不符,在編譯期也無法檢測,可能導致未定義錯誤。

3. 對於可變長參數,只能用__cdecl調用約定,因為只有調用者才知道傳進來幾個參數,所以也只有調用者才能維持棧平衡。如果是__stdcall,那麼函數需要負責棧平衡,可是函數本身根本不知道有幾個參數,函數調用結束後,根本不知道需要將幾個參數pop out。

initializer_list的方式

這是在C++11中新增的方法,如果所有的實參類型相同,就可以用C++11提供的標準庫類型initializer_list。

initializer_list是一種模板類型。可以看看initializer_list提供的一些操作:

C/C++11中的可變參數函數與模板

如果想給initializer_list形參傳遞一個實參的序列,必須把序列放在一對花括號內

C/C++11中的可變參數函數與模板

可變參數模板

可變參數模板(variadic template)就是一個接受可變數目參數的模板函數或模板類。使用時既不需要知道要處理的實參數目也不知道實參的數據類型。它的形式如下:

C/C++11中的可變參數函數與模板

其中Args是一個模板參數包;rest是一個函數參數包。

可變參數函數模板通常是遞歸的。第一步調用處理包中的第一個實參,然後用剩餘的實參調用自身。為了終止遞歸,我們還需要定義一個非可變參數的函數模板

C/C++11中的可變參數函數與模板

變長模板的優點:

1. 參數個數。對於模板來說,在編譯器模板推導的時候,就已經知道參數的個數了。

2.參數類型。在模板推導的時候模板函數的參數類型已經確定。

3. 既然編譯的時候就知道參數個數和參數類型,那麼調用約定也就沒有限制了。


分享到:


相關文章: