值传递和引用传递,以及const在函数中的用法

简述

理解值传递与引用传递,可以提高代码的运行效率;
理解const在函数中的用法,可以增强程序的健壮性,“Use const whenever you need"。
而const的用法针对值传递、引用传递又有很大的区别。
下文将分成难度递增的三个阶段,来记录值传递、引用传递和const修饰符在函数中的用法。

level 1–值传递与引用传递

1、值传递
主调函数向调用函数传递参数实际上只是将实参的拷贝(即临时副本)传递给了被调用函数,并不是实参本身。这样被调函数不能直接修改主调函数中变量的值,而只能修改其私有的临时副本的值。
临时的参数副本需要经过调用构造函数、拷贝、析构等过程,对于非内部类型的输入参数而言,会明显的影响程序的效率。
由于指针也是一个值,参数为指针时,传递给被调函数的实参是一个指针的拷贝,但这个指针指向的内容是同一个位置,故指针传递时,可以通过地址间接地改变实参的值。
2、引用传递
函数对引用的操作等于对其指定的对象进行操作,当将实参传递给形参时,形参就指向的实参(即形参与实参同义,是它的一个别名)。

level 2–const在函数声明中的用法

const可以修饰函数的参数、返回值,以及函数的定义体。
1、const修饰函数的参数
const只能修饰输入参数。
如果输入参数采用“值传递”,不要加const修饰。因为对于值传递函数将自动产生临时变量用于复制该参数,该输入参数本来就无需保护。例如下列写法没有意义:

void Func1(int x)写成void Func1(const int x)
void Func2(A a)写成void Funct2(const A a) //A为用户自定义数据类型

输入函数采用“引用传递”,仅借用了参数的别名,不需要产生临时对象,但有可能改变原参数的值。故加const修饰,最终函数写作 void Func(const A& a)。内部数据类型的参数不存在构造、析构的过程,而复制也非常快,“值传递”和“引用传递”的效率几乎相当。
2、const修饰函数的返回值
如果函数返回值采用“值传递”的方式,由于函数会把返回值复制到外部临时的存储单元中,加const修饰没有任何意义。
函数返回值采用“引用传递”的场合并不多,一般只出现在类的赋值函数中,目的是为了实现链表式表达。如下所示:

class A
{
	A &operate=(const A &other);  //赋值函数
};
A a, b, c; //a,b,c为A的对象
a = b = c; //正常的链式赋值
(a = b) = c; //不正常的链式赋值,但合法
如果将赋值函数的返回值用const修饰,该返回值的内容不允许被改动。
则a=b=c语句仍然正确,但语句(a=b)=c则是非法的。

如果以“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const修饰的同类指针。
3、const成员函数
任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其它非const成员函数,编译器将指出错误。
const修饰*this是本质,编译器报错的根源就是*this是const类型的。

level 3–const修饰指针和引用的用法

1、const修饰指针
1.1 const修饰指针本身
指针本身为常量,不可改变。
写法:int* const pi = xx;
1.2 const修饰指针指向的变量或对象
通过间接引用指针不可改变变量的值。假设指针为p,则*p不可变。
写法:const int *pi = xx 或 int const* pi = xx;
1.3 const修饰指针本身和指针所指的变量或对象
设有指针p,此种情况下,p和*p都不可变。
写法:const int* const pi = xx;
2、const修饰引用
引用被const修饰只有一种类型。
引用本身不可变,但引用的变量或对象可以改变。
3、const修饰指针的引用
引用只是个别名,这里与const修饰指针相同。

写在最后

对自己提两个要求:一是尽量在编写函数是使用引用传递来传参;二是尽量多的使用const修饰函数。

猜你喜欢

转载自blog.csdn.net/lusanshui/article/details/85099749
今日推荐