在头文件中进行函数声明
建议变量和函数应该在头文件中声明,在源文件中定义。
使用引用避免拷贝
如果函数无须改变引用形参的值,最好将其声明为常量引用。
// 比较两个string对象的长度
bool isShorter(const string &s1,const string &s2)
{
return s1.size()<s2.size();
}
尽量使用常量引用
bool is_empty(const string& s) { return s.empty(); }
表示数组大小的形参
void print(const int ia[],size_t size) // 等价于const int* ia
{
for(size_t i=0; i!=size; ++i)
cout << ia[i] <<endl;
}
数组引用形参
// 正确:形参是数组的引用,维度是类型的一部分
void print(int (&arr)[10])
{
for(auto elem:arr)
cout << elem << endl;
}
f(int &arr[10]); // 将arr声明成了引用的数组
f(int (&arr)[10]); // arr是具有10个整数的整型数组的引用
int *matrix[10]; // 10个指针构成的数组
int (*matrix)[10]; // 指向含有10个整数的数组的指针
initializer_list
如果函数的实参数量未知但是全部实参的类型都相同,可以使用initializer_list类型的形参。
和vector一样,initializer_list也是一种模板类型,定义initializer_list对象时,必须说明列表中所含元素的类型。
initializer_list<string> ls;
initializer_list<int> it;
和vector不一样的是,initializer_list对象中的元素永远是常量值,无法改变initializer_list对象中元素的值。
如果想向initializer_list形参中传递一个值的序列,则必须把序列放在一对花括号内。
void error_msg(ErrCode e,initializer_list<string> il)
{
cout << e.msg() << ":";
for(const auto &elem:il)
cout << elem << " ";
cout << endl;
}
// expected和actual是string对象
if(expected != actual)
error_msg(ErrCode(42),{"functionX",expected,actual});
else
error_msg(ErrCode(0),{"functionX","okay"});
省略符形参
省略符形参是为了便于C++程序访问某些特殊的C代码而设置的,这些代码使用了名为varargs的C标准库功能。省略符形参应该仅仅用于C和C++通用的类型。特别应该注意的是,大多数类类型的对象在传递给省略符形参时都无法正确拷贝。
省略符形参只能出现在形参列表的最后一个位置。
void foo(parm_list,...);
void foo(...);