Cpp_浅谈形参中const和引用的作用
1、可以确定的是,如果你想修改传入的引用对象,不可以加const修饰。不管是指针还是引用,前面加const之后,比如const A *
或const A &
,都会导致A只可读、只能调用其常方法,常方法一般不可以修改其成员属性。
因此,针对于《流类对象》,99%的情况下不加const。
2、const的目的在于两方面,字面意思是修饰其不可修改,还有一个很重要的目的在于使可接收的对象属性范围更大。如果形参定义为const属性,既可接收“非const对象”,也可接收“const对象”。所以,如果在函数中不涉及到对传入的对象进行修改时,都尽量加const。
比如,形参是const string str
。如果外部传入的是字符串常量"aaa"
,照常接收,如果形参是string str
,无法接收,实参的通用性收到限制。
3、接下来就是富含争议的引用修饰了。
在C中,语义上,引用是一个变量的别名;调用效果上,如果是按引用传递,则被调用者和调用者操作的是同一个对象。
在语法上,C的普通引用本质上是一个“指针指向的地址信息不可变,而指向的内容可变”。
1 | Typename t; |
在程序中,编译器会自动处理对其进行解引用。
用在参数传递中,如果要修改对象,可视为语法糖,隐含了指针的解引用操作。
如果用在参数传递中,却不涉及到修改对象,引用有时可视为对性能的优化,有时可以避免对象在传递过程中产生不必要的临时对象拷贝、析构。但是,在实际生产项目中,此举尚需要论证其必要性。因为有时即使你是按引用传递的,但是避免不了会出现隐式构造临时对象。比如字符串常量"aaa"传给一个const string & str。
要注意的是,传递引用是有风险的,程序员必须明确对象在程序中完整的生命周期,需要保证被引用的对象的生命期要长于函数的调用点。要明确对象在堆栈上的产生时机、析构时机,才能安全地传递引用。
如果从代码规范上角度来考虑,尽量向安全、统一的形式靠拢,即统一的按值传递。这也是Java规范按值传递的一大优势,避免了C++程序设计的复杂性,但是某时会有一定的性能损耗。
总之,函数接收参数的类型设计没有一个统一的方法论,要设计出一个优秀的代码程序,你必须清楚你整个程序的生命周期及其所存在的风险,要时刻搞清楚你的代码中传参的目的是什么。最后在此基础上,在代码规范和性能调优上做出平衡。