C++细节(二)
3.1 左值引用
左值引用,其声明是通过在某个类型后放置一个 & 符号来进行的。
此时,一个左值引用成为了它所引用的对象的同义词。如图
当然,左值引用有以下的几个用途:
1. 给结构复杂的名称起别名
auto & whichList = theList[myhash( x, theList.size() )]; //起别名
if (find(begin(whichList),end(whichList),x)!=end(whichList))
return false;
whichList.push_back(x);
2. 范围for 循环
for (auto & x :arr) ++x; //arr 为vector 对象
实际上也是让x是vector中每个值的另一个名字,使for循环变得更简洁一些。
3. 避免复制
假设有一个findMax函数是返回一个大集合中的最大值,用左值引用可以避免对象的复制。如,
auto &x =findMax( arr ); //而不是用auto x=findMax( arr )
3.2 参数传递
C++11中有4种传递参数的方法:
1.传值调用
在许多编程语言中,运用传值调用传递所有参数。而它却不是C++11的唯一传递机制。传值调用使的原实际参数保持不变。
2.传引用调用
比如,swap (x,y)需要交换x和y 的值,即改变x和y 的值就不能用传值调用的方法。交换函数的定义如下:
viod swap(&x ,&y) {....}
3.传常量引用调用
对于 string randomItem( vector<string> arr) 函数是返回arr 中的一个随机项,未对其做任何改变。
而其中,传值调用的使用使vector 对象进行了复制,增加了程序运行的开销,是应避免使用的做法。
因此,传常量引用调用可以通过声明arr 为对vec 的常量引用以避免复制而达到相同的语义效果,如下:
string randomItem( const vector<string> & arr);
4.传右值引用调用
其核心概念在于,由于右值存储的是要被销毁的临时量,像 x=rval可以通过移动而不是复制实现。
4种传递参数选择的注意事项:
1. 对于小的不应被函数改变的对象,选择传值调用合适。
2. 对于大的不应被函数改变的且复制代价昂贵的对象,采取传常量引用调用合适。
3. 对于所有可以被函数改变的对象,则选择传引用调用。
参考资料:https://blog.csdn.net/u012814856/article/details/83410552
3.3 返回值传递
同样在C++中函数返回也有几种机制。不同类型的返回应选择相应的返回机制,以提高程序的效率,如
double avg( double x,double y); //返回均值
LargeType random(const vector<LargeType> &arr); //潜在低效
vector<int> partialSum(const vector<int> &arr); //较高效
代码的第一行是传值返回,是一种简单直接的机制。对于第三行则需要运用传常量引用返回以避免直接复制,具体代码如下所示,
LargeType random1( const vector<LargeType> &arr )
{
return arr[random(0,arr.size()-1)];
}
const LargeType random2( const vector<LargeType> &arr )
{
return arr[random(0,arr.size()-1)];
}
Vector< LargeType> vec;
....
LargeType item1 = random1(vec); //复制
LargeType item2 = random2(vec); //复制
const LargeType &item3 =random2(vec); //不复制
注意,传常量引用返回的调用者必须也使用常量引用以存取这个返回值,否则仍将进行复制。
第三种是传引用返回 ,既不产生拷贝,并且还能对其值进行修改(这种情况虽然少见,但是也有存在)。
参考资料:https://blog.csdn.net/u012814856/article/details/84099328