C++ 左值與右值 右值引用 引用折疊 => 完美轉發


左值與右值

什么是左值?什么是右值?

在C++里沒有明確定義。看了幾個版本,有名字的是左值,沒名字的是右值。能被&取地址的是左值,不能被&取地址的是右值。而且左值與右值可以發生轉換。

我個人的理解就是在當前作用域下右值是個臨時變量。

舉例如下:https://blog.csdn.net/wangshubo1989/article/details/50479162

// lvalues:
  //
  int i = 42;
  i = 43; // ok, i is an lvalue
  int* p = &i; // ok, i is an lvalue
  int& foo();
  foo() = 42; // ok, foo() is an lvalue
  int* p1 = &foo(); // ok, foo() is an lvalue

  // rvalues:
  //
  int foobar();
  int j = 0;
  j = foobar(); // ok, foobar() is an rvalue
  int* p2 = &foobar(); // error, cannot take the address of an rvalue
  j = 42; // ok, 42 is an rvalue

 

照搬了別人的例子。(尷尬)


右值引用

以前在拜讀muduo的時候就遇到過右值引用T&&。當時沒詳細了解,就知道配合std::move使用,是移動構造函數A(A&& a)中使用的。

后來才知道他其實是右值引用

具體關於move以及移動構造函數我以前以及了解過,也使用比較多,此處不用記錄了C++11中移動語義(std::move)和完美轉發(std::forward)也有所解釋,我更看中他對forward的解釋(笑~)


引用折疊 => 完美轉發

什么是引用折疊?

來自C++11中移動語義(std::move)和完美轉發(std::forward)

不過還是很難理解這和完美轉發的實現有什么關聯?為什么引用折疊能讓forward完美轉發參數原來的左值右值屬性?

感覺是這文的的實例代碼一段講述了forward的好處,后一段其實是嚴重引用折疊的,所以我沒看懂

//https://en.cppreference.com/w/cpp/utility/forward
#include <iostream>
#include <memory>
#include <utility>
 
struct A {
    A(int&& n) { std::cout << "rvalue overload, n=" << n << "\n"; }
    A(int& n)  { std::cout << "lvalue overload, n=" << n << "\n"; }
};
 
class B {
public:
    template<class T1, class T2, class T3>
    B(T1&& t1, T2&& t2, T3&& t3) :
        a1_{std::forward<T1>(t1)},
        a2_{std::forward<T2>(t2)},
        a3_{std::forward<T3>(t3)}
    {
    }
 
private:
    A a1_, a2_, a3_;
};
 
template<class T, class U>
std::unique_ptr<T> make_unique1(U&& u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)));
}
 
template<class T, class... U>
std::unique_ptr<T> make_unique2(U&&... u)
{
    return std::unique_ptr<T>(new T(std::forward<U>(u)...));
}
 
int main()
{   
    auto p1 = make_unique1<A>(2); // rvalue
    int i = 1;
    auto p2 = make_unique1<A>(i); // lvalue
 
    std::cout << "B\n";
    auto t = make_unique2<B>(2, i, 3);
}

 

rvalue overload, n=2

lvalue overload, n=1

B

rvalue overload, n=2

lvalue overload, n=1

rvalue overload, n=3

 結合此段代碼就可以感覺到,雖然B(T1&&,T2&&,T3&&)的參數都是右值引用,結合應用折疊規則,其轉入的參數都會保留原有的右值引用和左值引用屬性

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM