如果函式想要能接受不定長度的引數(Variable-length argument),基本上可以使用 vector
定義參數,而呼叫方使用 vector
收集引數後,再來呼叫函式,例如:
#include <iostream>
#include <vector>
using namespace std;
void foo(vector<double>);
int main() {
vector<double> args;
args.push_back(1.1);
args.push_back(2.2);
args.push_back(3.3);
foo(args);
return 0;
}
void foo(vector<double> args) {
for(auto arg : args) {
cout << arg << endl;
}
}
現代程式語言,不少都提供了定義不定長度引數的特定語法,令呼叫函式時可以更自然,像是 foo(1.1, 2.2, 3.3)
,就這點而言,C++ 11 可以有兩個方案,一是定義參數型態為 initializer_list
,透過清單初始化(list initialization)令呼叫函式的語法更方便一些;另一個方式是透過可變參數模版(variadic template)來定義,這需要認識模版語法等更多細節,之後再來談。
initializer_list
定義於 initializer_list
標頭檔,來看看如何使用:
#include <iostream>
#include <initializer_list>
using namespace std;
void foo(initializer_list<double>);
int main() {
foo({1.1, 2.2, 3.3});
return 0;
}
void foo(initializer_list<double> args) {
for(auto arg : args) {
cout << arg << endl;
}
}
在呼叫函式時,使用了清單初始化 {}
包含了引數,實際上,如果 foo
定義參數時使用 vector
,這個範例也可以運作,那為何要改為 initializer_list
?因為清單初始化 {}
會建立 initializer_list
,而 vector
不過就是有個建構式,可以接受 initializer_list
,才令 vector
也可以使用清單初始化。
簡單來說,只是想定義不定長度引數時,initializer_list
就可以了,不過它包含的方法比較少,如果需要 vector
的方法,使用 vector
當然也是可以。
C++ 中也可以使用 C 風格的不定長度引數,然而並不建議,若要與具有 C 風格的不定長度引數互動,可以包含 cstdarg
標頭檔,底下是個範例:
#include <iostream>
#include <cstdarg>
using namespace std;
void foo(int, ...);
int main() {
foo(3, 1.1, 2.2, 3.3);
return 0;
}
void foo(int size, ...) {
va_list args;
va_start(args, size);
for(int i = 0; i < size; i++) {
cout << va_arg(args, double) << endl;
}
va_end(args);
}