本节书摘来自异步社区出版社《C++面向对象高效编程(第2版)》一书中的第3章,第3.14节,作者: 【美】Kayshav Dattatri,更多章节内容可以访问云栖社区“异步社区”公众号查看。
3.14 为参数选择正确的模式
C++面向对象高效编程(第2版)
尽可能避免按值传递大型对象。对于基本类型和小型对象,可按值传递。复制对象的开销很大,但是,如果主要考虑安全问题,则应坚持按值传递。
需要传递对象时,不要传递指针。
`
void f (T* object);`
(1)指针无法保证它确实指向某对象,它很可能是一个空指针。
(2)如果被调函数需要将真正的对象作为参数,则传递引用,而不是指针。这可确保不出现问题,被调函数无需检查空引用(因为不可能出现这种情况)。
(3)如果希望被调函数在对象中写入(输出形参),则传递引用,但不是对const的引用。
(4)传递引用并不意味着将对象的所有权移交给被调函数。主调函数仍然拥有对象(且对其负责)以及与该对象相关的内存。如果被调函数希望主调函数放弃对象的所有权,应在文档中清楚地说明。否则,双重删除(double delete
)会导致程序无法正常运行。[多次释放(在C++中为delete
,C中为free
)一个指针所指向的动态内存地址时,会发生双重删除。使用new()
分配的内存只能使用delete操作符删除一次。但是有时,由于程序出错,相同的指针会被多次删除。]
(5)被调函数需要检查指针是否为空,才能使用它。这样的接口非常不好用,而且难以追踪。如果确实需要,应在文档中清楚地说明,以免混淆。
当传递基本类型参数时,要坚持使用值参数(value argument
)。传递指针和传递整数的开销一样,但是,按值传递更安全。
在可以使用默认值参数的地方,尽可能使用默认值参数。它们不仅包含更多信息,还有助于理解参数的用途和减少了客户的负担。客户只需传递较少的参数。
尽量对参数和函数使用const限定符。前面介绍过,编译器能识别const限定符,这样做让编译器也参与其中,使得程序更加强健稳定。
如果希望在参数中使用多态(后续章节将介绍),则必须使用引用或指针参数,不能使用按值传递。此规则也适用于返回值(在下面说明)。
注意:
无论何种规则,都有一些例外,特别是将指向基本类型的指针作为参数时。即使不涉及转移所有权,也应按照惯例,传递指向基本类型(特别是字符指针,char*
)的指针。这是因为指针允许导航(使用++和--操作符),而引用并没有这种灵活性。在大多数情况下,这样的指针都用来作输出和输入/输出形参(参见strcpy
、strcat
等库函数)。如果在接口中发现使用未转移所有权的普通指针时,不要感到惊讶。不过,这样的接口必须在文档中详细地说明。由于指针的灵活性,甚至当传递未转移所有权的对象时,在某些情况下也要使用指向这些对象的指针,而不是引用。方法可以要求指向对象的指针参数,但要带有默认值NULL,这允许主调函数在调用方法时可省略参数。在这种情况下,指针将用于指出哪个参数是可选的,而引用参数却很难做到这一点,因为它没有独特的值来区分非法引用(每个引用都是合法的引用)。因此,要养成遵循一些规则,但同时也记住例外的好习惯。无论如何,都要在文档中清楚说明这样的接口,以避免出现混淆。
本文仅用于学习和交流目的,不代表异步社区观点。非商业转载请注明作译者、出处,并保留本文的原始链接。