美文网首页程序员C++2.0
C++右值引用和移动语义学习小结

C++右值引用和移动语义学习小结

作者: linjinhe | 来源:发表于2018-08-25 22:13 被阅读5次

    在 C++11 之前,将一个对象移动(move)到另一个对象的通用做法只有 copy constructor 或者 copy assignment ,然后销毁原来的对象。如果这个对象的创建涉及动态内存分配的话,copy constructor 或者 copy assignment 的开销就可能比较大。

    从 C++11 开始,C++ 引入了移动语义(move semantics)。由此 C++11 的 class 也多了两个特殊的成员函数 —— move constructor 和 move assignment。
    引入移动语义,首先要做的第一件事就是,如何确定该用 move 还是 copy ?
    为此 C++11 引入了右值引用这个概念 —— 在 C++ 里所有的右值都可以被移动。

    这里又有了另一个问题:什么是右值引用、右值?相对的还有左值引用、左值?
    左值与右值这两概念是从 C 语言中传承而来的。在 C 语言中,左值指的是既能够出现在等号左边也能出现在等号右边的变量(或表达式),右值指的则是只能出现在等号右边的变量(或表达式)。
    左值可以取到其内存地址,右值不能。左值与右值的根本区别在于能否获取内存地址。
    左值引用和右值引用,其实就是左值的引用和右值的引用。他们俩都是引用,区别在于引用的数据是啥。
    注意,左值引用和右值引用都是左值。

    下面举几个简单的列子:

    int i = 42;                 // i 是个左值,42 是个右值
    int& r = i;                 // r 是个左值引用
    int&& rr = i;               // 错误,不能将左值 i 绑定到右值引用 rr 上
    int&& rr1 = std::move(i);    // std::move 将 i 强制转换成一个右值
    int &r2 = i * 42;           // 错误: i * 42 是一个右值,不能绑定到一个左值引用
    const int &r3 = i * 42;     // 可以将一个右值绑定到一个 const 的左值引用
    int &&rr2 = i * 42;         // 将右值绑定到右值引用
    

    从上面的例子可以看到,有两种引用可以绑定到右值:const 左值引用和右值引用

    当传入的对象是右值且支持 move constructor 或 move assignment 时,C++ 会使用移动语义的函数。如果不支持移动语义的函数,无论传入的对象是右值还是左值,C++ 还是会使用复制语义的函数。
    因为左值引用和右值引用其实都是左值, C++11 提供了一个函数 std::move 可以将一个对象强制转换成右值(rvalue)。

    移动语义的出现,一方面可以让编译器在某些情况下,使用 move 而不是 copy 来提升程序性能。另一方面,让一些 move-only 的类型在语义上更加明确,如 std::unique_ptrstd::futurestd::thread

    更多关于右值引用、移动语义的内容,请参考

    • C++ Primer 5th, 13.6 Moving Objects
    • Effective Mordern C++, Chapter 5 Rvalue References, Move Semantics, and Perfect Forwarding

    最后,附上之前整理的电子书下载链接:C++ 学习资料整理(电子书)

    相关文章

      网友评论

        本文标题:C++右值引用和移动语义学习小结

        本文链接:https://www.haomeiwen.com/subject/tycniftx.html