右值引用
右值引用
1. 什么是右值引用
右值引用是C++11新加的一種引用類型,是一種僅能綁定到右值上的引用。不同于左值引用僅用一個&表示,右值引用用兩個&&表示。
int x{ 5 }; int& lref{ x }; // l-value refrence initialized with l-value x int&& rref{ 5 } // r-value refrence initialized with r-value 5右值引用有兩個非常有用的性質: 1. 右值引用將初始化他們的對象的壽命延長到右值引用的壽命;2. 非常量的右值引用允許修改右值。
看一個實際例子:
#include <iostream>class Fraction { private:int m_numerator;int m_denominator;public:Fraction(int numerator = 0, int denominator = 1) :m_numerator{ numerator }, m_denominator{ denominator }{}friend std::ostream& operator<<(std::ostream& out, const Fraction &f1){out << f1.m_numerator << '/' << f1.m_denominator;return out;} };int main() {auto &&rref{ Fraction{ 3, 5 } }; // r-value reference to temporary Fraction// f1 of operator<< binds to the temporary, no copies are created.std::cout << rref << '\n';return 0; } // rref (and the temporary Fraction) goes out of scope here這段代碼打印出:
3/5Fraction{ 3, 5 }是一個匿名對象(臨時對象),在這行語句結束的時候就出了作用域,本來應該被銷毀掉,但是我們用了一個右值引用來綁定它,因此延長了它的生命期,直到main函數結束,局部變量rref被銷毀的時候,這個臨時對象才會被銷毀。
再看另外一個例子:
這段代碼執行結果是:
10這里用字面值初始化一個右值引用,會創建一個臨時對象,我們可以通過右值引用來修改這個對象。
2. 右值引用作為函數參數
右值引用最有用的地方在于作為函數參數,尤其是在寫重載函數時,希望對傳入的左值和右值表現出不同的行為。
void fun(const int& lref) {std::cout << "l-value reference to const." << std::endl; } void fun(int &&rref) {std::cout << "r-value reference." << std::endl; }int main() {int x{ 5 };fun(x); // l-value argument calls l-value version of fun()fun(5); // r-value argument calls r-value version of fun()return 0; }這段代碼打印出:
l-value reference to const. r-value reference.可以看出,當傳入的參數是左值時,調用的是左值版本的fun(), 當傳入的參數是右值時,調用的是右值版本的fun()。可是這有什么用呢?這對于移動語義來說是一個非常重要的特性,后面會繼續討論。
再看一個有意思的例子:
ref是一個右值引用,那么fun(ref)調用的是右值引用版本嗎?事實上,這里調用的是左值版本的fun()函數。雖然ref是一個右值引用,但是這僅說明它綁定的對象是一個右值,它本身是一個局部變量,是一個左值,因此這行代碼調用的是左值版本的fun()。
3. 不要返回右值引用
在絕大多數情況下,你都不應該返回右值引用。因為右值引用綁定的對象在出作用域之后就會被銷毀,因此從函數返回,你智能得到一個"hanging reference"。
參考資料
[1].https://www.learncpp.com/cpp-tutorial/15-2-rvalue-references/
總結
- 上一篇: 华为云桌面云中心调试步骤_轻松进行云维护
- 下一篇: MFC+Opencv4+vs2017 显