c11右值引用--笔记

C11中有左值引用和右值引用

 

左值引用

对一个变量的别名,不会调用拷贝构造,对别名的操作影响原值

eg:

 

 

运行结果:

 

 

 

右值引用

对匿名变量的引用,提出右值引用的原因:充分利用在函数调用过程中产生的临时变量,对这个临时变量达到最大限度的使用率

 

常用的匿名变量(对象):

 

fun(A a());           //此时生产了一个临时变量,且无名,这就是右值

 

int  add(int a, int b)

{

       return (a + b);   //此时的(a+b)的结果就是一个临时变量,且无名,这就是右值

}

 

 

右值引用如何使用

并不是变量自动就会变成右值引用,需要用户按右值引用的方式定义接口、定义变量,才会触发右值引用,举个例子:

1)

 fun (A a) { //再怎么传也不会变成右值引用

//TODO

}

如果用户使用  fun(A()); //则就是调用一个普通的函数

 

2)

如果想使用右值引用就需要用户按右值引用定义接口,才会调用到这个右值引用

fun(A&& a){

//TODO

}

 

fun(A());   //这时编译器发现你有定义相关接口,就会去调用右值引用的函数了

 

记住: 右值引用可以优化过程中产生的临时变量,但并不代表你什么都不做它就能优化,如果你想优化,需要你手动实现相关接口才行;  右值引用只是一个功能,你可以选择用或不用。

 

 

上面1)和2)说的都是调用函数中的形参问题,下面说说变量问题;

 

int a=2, b=3;

 

int     c = add(a, b);         //c就是再普通不过的一个左值,add先产生一个临时变量然//后再将临时变量赋值给c

int&&  d = add(a, b);         //d就是一个右值,add过程中产生一个临时变量,d就是这//个临时变量的一个“引用”,加引号是因为说d是一个偷盗//者更合适,它把那个临时变量给偷过来了

 

注意:此处使用int并不是很明显,如果使用一个T,T中包含指针数组,大家可能更容易明白

 

 

上面的c和d是程序员用户自己写的,他不在乎过程中多一次拷贝就按c的方式写;如果他是一个处女座的程序员,他可能更喜欢使用d的方式;再次重申:右值引用是一功能选项,你可以选择用与不用。

 

 

 

扩展一

 

上面说的都是最正常的情况,即只对匿名变量(对象)使用右值引用,但是我们总是喜欢知道了一个规则后,就千方百计利用这个规则,比如下面这种使用场景:

void test(){

T t;

fun(std::move(t));       //将t转换成了一个右值引用

 

}

 

 

void fun(T& t);    //左值引用

 

void fun(T&& t);  //右值引用

 

 

举一个可能用到的场景:

void print_(std::string&  str) {

       std::cout<<str<<”\n”;

}

 

void print_(std::string&& str) {

       std::cout<<str<<”\n”;

}

 

void test() {

       std::string str(“Hello World!”);

       print_(str);                      //左值引用,后面str内容不变

       print_(std::move(str));          //转为右值引用 ,表示str可以被移动,但是否移动看后面接口的选择了,由于此处仅是调用一个接收右值引用传递的方法,

                                                   //并不会修改str,即并没有进行move操作,所以调用完成后str内容不会发生改变

}

 

注意std::move的本质,它其实就是一个转换函数,将给定的类型转化为右值引用,而并不是真正地“移动”了资源.

  

posted @ 2018-11-09 18:53  郭流水  阅读(1839)  评论(1编辑  收藏  举报