传参的四种方式
按值传参
在调用函数时,将实参的值拷贝给形参,形参在函数中被使用。对形参的操作不会影响到实参的值。但是因为发生了拷贝会增加系统开销。
ps:传指针也是传引用的一种,因为指针就是一种特殊的变量。
按左值引用传参
那么怎么才能不发生拷贝,也不增加系统开销呢?或者是我们需要对实参的值进行操作呢?答案就是传引用作为参数。(也叫按(左值)引用传参)
引用相当于实参的别名,相当于在函数中直接操作实参,也没有发生拷贝自然也就没有增加系统开销。函数中对引用的操作也会引发对实参值的改变。
按常量引用传参
有时候我们只是希望减少系统开销,不进行传值拷贝,但是我们不想在函数中改变实参的值怎么办呢?于是,按常量引用传参也就来了,我们都知道被const修饰的变量的值是不能被改变的,所以在函数中我们只能取到实参的值,但是我们没有办法进行修改,同时也保留了减少拷贝开销的优点。
按右值引用传参
按右值引用传参是c++11新增的语义。
对于右值来说,其存储的是临时的将要被摧毁的资源,移动一个对象的状态总会比赋值这个对象的状态要来的简单(开销小)。
实际开发中该如何选择
返回传值的三种方式
我们首先思考几个问题,在c++返回传值的表现:
1、被传递的值是否持续存在?
2、传递的过程中是否发生了拷贝
3、传递过程中是否会自动转化为移动语义(c++11新增)
4、…等等
这几个问题主要与两方面有关系:
1、被返回的值
被返回的值有以下两种:
1、左值还是右值
2、临时变量(作用域在函数内)还是非临时变量(函数外定义的)
当被返回的值是一个右值或者临时变量时,我们选择直接将其值移动到返回接受这个值的地方,节省资源开销,c++就是这样做的。
2、返回类型
返回类型分为三种:
1、按值返回,产生拷贝
2、按常量引用返回,则如果调用方使用常量引用接受返回值则不产生拷贝。
3、按引用返回,则既不产生拷贝,并且还能对齐值进行修改(罕见)
按值返回
int randInt(const vector&arr)
{
return arr[randomInt(0,arr.size() - 1)];
}
vectorvec;
int a = randInt(vec);
最常见的返回值不多说,发生拷贝。因为被返回的值不是临时变量,而是一个非临时变量的左值,在返回传值的时候,将它的值拷贝给a变量。
按常量引用返回
既然传值返回会出现拷贝开销,为了解决这个问题,我们的返回值类型选择引用不就可以了吗。我们常选择(常量)引用的方式。
注意这里我们调用方的变量需要也是常量引用,不然会发生(const转非const)拷贝转化的。
按引用返回
按引用返回的场景比较少,多见于调用者需要对于返回对象的内部的数据进行修改。