左值與右值
什么是左值?什么是右值?
在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&&)的參數都是右值引用,結合應用折疊規則,其轉入的參數都會保留原有的右值引用和左值引用屬性