C++ 右值引用

来源:互联网 发布:中超风云球员数据 编辑:程序博客网 时间:2024/04/28 16:55

右值引用


今天平安夜,要不是女巫用药,要不是狼人一刀刀长老身上了。。。
开个玩笑。。。

  • 右值引用
    • 起源
    • 左值右值
    • 右值引用的应用
    • 参考


起源

因为同学的大作业看了看模板类,可能以前学得也比较糙,也有可能之前用的书没有讲到C++ 11的新特性所以并没有注意到这个概念,直到看到如下代码《C++ Primer》(第5版)584页:

template <typename T> class Blob{public:    //...    void push_back(T &&t);//移动版本    //...};

居然第一次看到双取地址符的写法,一下子把我看呆了,都不知道怎么查。。StackOverFlow上面显然有人跟我遇到了一样的问题,http://stackoverflow.com/questions/4549151/c-double-address-operator。。这种写法就代表右值引用(rvalue reference)


左值右值

说起这个真的是个非常让人头疼的概念:
左值是一个指向某内存空间的表达式,并且可以通过&获取内存,而右值就是非左值。这种解释真是让人云里雾里的,简单的来说,“左值既可以在赋值号的左边也可以在赋值号的右边,而右值只能出现在右边。”,这个论断在大多数情况下是有效的,比如说:

int a=10;int b=(a+1);//b是左值int c=b;a+1=c;//error a+1是右值

再举个例子说:
在编译器里面敲下如下代码:

int i=1;++(i++);//编译器报错

这里错误提示:表达式必须是可修改的左值,而如果这样写:

int i =1;(++i)++;

就没有问题。
说远点,以前有人问i++,和++i两个表达式究竟哪个效率高?
http://stackoverflow.com/questions/24853/what-is-the-difference-between-i-and-i
一个说法是++i效率高,因为++i返回左值,并不进行拷贝操作,而i++返回的则是右值。
仔细研究这两个表达式的过程就更加清晰了:

//i++{    int temp = i;    i=i+1;    return temp;}//++i;{    i=i+1;    return &i;}

想起之前学习const的时候说过一点c++ const限定符,因为必须将左值绑定到引用上,但是使用常量引用去“绑定”一个右值,示例:

int &i=1;//error  非常量引用的初始值必须为左值const int &i=1;//ok相当于{    const int temp=1;    const int &i = temp;}

扯远了,简单的理解,左值是一个对象,右值是一个值。


右值引用的应用

加入右值引用的概念,当然要跟左值引用区分了,其实左值引用就是我们之前认知世界中的引用,而新标准中为了区分左值右值引用,用双取地址符(&&)来指代右值引用,其好处是可以实现移动语义(Move Sementics)和精确传递(Perfect Forwarding),回到最早提到的关于push()函数的移动版本:

template <typename T> class Blob{public:    //...    void push_back(T &&t);//移动版本    //...};

在使用时,我们要额外使用新标准提供的std::move()函数:强制实现转移语义,直接使用变量的返回值,并强制认为是一个右值,这个函数也将返回该右值引用。在某些编译换进下,move()函数还起到了swap()的功能:

std::string str = "Hello";std::vector<std::string> v;v.push_back(str);v.push_back(std::move(str));

通过单步调试观察string str,和vector<string> v的值,结果如下:

单步结果1
单步调试结果1

单步调试2
单步调试结果2

在使用移动语义的时候发现str的为空了,这是因为作为一个右值,他已经return了。


参考

http://en.cppreference.com/w/cpp/utility/move
http://www.cplusplus.com/reference/utility/move/
http://www.zhihu.com/question/22111546
http://jxq.me/2012/06/06/%E8%AF%91%E8%AF%A6%E8%A7%A3c%E5%8F%B3%E5%80%BC%E5%BC%95%E7%94%A8/

1 0
原创粉丝点击