Google C++ Coding Style定义
输入参数以值或者const引用形式传入,输出参数使用指针。 所有以引用形式输入参数必须加上const,即const T&的形式。
即如下形式:
void Foo(const string &in, string *out);
在如下情况下, 可以使用const T*的形式:
* 需要进行指针的判空 (即空指针是合理的)。
* 需要使用到输入参数的指针或引用形式。
为什么要使用const T&形式?
以值传入是最为安全的形式,因为它总是提供一个复本到函数中。对于复杂的参数(结构或类),这也引入了不必要的拷贝的开销。使用指针及引用都可以解决这个问题。而引用则更为安全,可以避免一些不必要的空指针判断。所以输入参数以const T&的形式的定义, 与传递值的语义相似,既避免了拷贝,又避免了意外修改。
下面这个例子,则表现出函数即使定义为const T&形式,仍然可能出现空指针引入的问题:
void test(const A& a) {
a.max = 10;
}
A* b = NULL;
test(*b);
这是一个错误使用引用的示范,语法上合法,但这样的实现是不允许的。判空的责任在于调用者,而不在函数。(参考:How do you check for NULL when passing by reference in C++?)
另外,因为传引用,在其本质也是以指针形式提供的,所以在性能相对于传值会低一些的。所以简单的数据类型还是要传值。
输出参数为什么是指针呢
以引用和指针的形式,都可以作为函数的输出参数。如果没有const修饰引用,则引用形式的参数就可以成为一个输出参数。这可能会让代码的读者对参数的类型产生错觉。正是Google C++ Coding Style中所描的: 引用有着和值类的语法,但却是指针的语义。代码的读者会对能不能改变一个参数的值产生疑问, 以为传入的是Value, 但值却改变了。虽然看一下函数声明就可以了,但如果一个大型项目,还是要追求做到一目了然。
总结
作为编码规范定义出来的,主要是为了统一大家的编码习惯,减少一些”惊喜”。单纯从传值,传引用,亦或传指针的形式,cplusplus.com上的一篇也可以作为参考When to pass parameters by value, reference, and pointer。总结一下参数三种传入形式的核心点:
1. 传值性能最高,但有拷贝的开销。
2. 传引用时空值是不合法的,不用判空,没有拷贝的开销。
3. 传指针时空值是合法的,需要判空,也没有拷贝的开销。