精华内容
下载资源
问答
  • 右值引用

    2020-10-19 15:35:13
    右值引用 1. 什么是右值引用 右值引用是C++11新加的一种引用类型,是一种仅能绑定到右值上的引用。不同于左值引用仅用一个&表示,右值引用用两个&&表示。 int x{ 5 }; int& lref{ x }; // l-value ...

    右值引用

    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/5
    

    Fraction{ 3, 5 }是一个匿名对象(临时对象),在这行语句结束的时候就出了作用域,本来应该被销毁掉,但是我们用了一个右值引用来绑定它,因此延长了它的生命期,直到main函数结束,局部变量rref被销毁的时候,这个临时对象才会被销毁。
    再看另外一个例子:

    #include<iostream>
    int main()
    {
        int &&ref{ 5 };
        rref = 10;
        std::cout << rref << std::endl;
        return 0;
    }
    

    这段代码执行结果是:

    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()。可是这有什么用呢?这对于移动语义来说是一个非常重要的特性,后面会继续讨论。
    再看一个有意思的例子:

    int &&ref{ 5 };
    fun(ref);
    

    ref是一个右值引用,那么fun(ref)调用的是右值引用版本吗?事实上,这里调用的是左值版本的fun()函数。虽然ref是一个右值引用,但是这仅说明它绑定的对象是一个右值,它本身是一个局部变量,是一个左值,因此这行代码调用的是左值版本的fun()。

    3. 不要返回右值引用

    在绝大多数情况下,你都不应该返回右值引用。因为右值引用绑定的对象在出作用域之后就会被销毁,因此从函数返回,你智能得到一个"hanging reference"。

    参考资料

    [1].https://www.learncpp.com/cpp-tutorial/15-2-rvalue-references/

    展开全文

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 4,898
精华内容 1,959
关键字:

右值引用