文章在此
虽然,purecpp.org更新不怎么频繁,但其原来的内容,还是有很多宝贝的.只是有些 排版,实在不是很好.不过,学习为主.
上一篇是d的右值引用.这一篇是c++的.
这是最后的结论:
实现就是:静转<T&&>,将T/T&/T&&转为T&&,这样就是右值引用了.右值引用就是个废物利用..如果看懂了,就不必再看了.

1,左值引用:整&i=j;.
2,右值引用:整&&j=22;
右值引用解决的是:临时对象不必要的复制操作模板参数按实际类型转发(完美转发).
右值引用相关概念:右值,纯右值,将亡值,一般引用(universal...),引用折叠,移动语义,完美转发.

四行学右值引用

第一行:int i = getVar();

这个getvar()变量返回临时值,在表达式结束后就没了,这个值就是纯右值右值.能对表达式取地址,即为左值,否则为右值.
具名变量都是左值.字面量都是右值.右值不具名.
右值表达式结束后就不存在的临时对象.
值=左值+右值,右值=将亡值+纯右值,
纯右值:非引用返回的临时变量,表达式产生的临时变量,字面量,入表达式(注意这个).
将亡值:与右值引用相关的表达式:要被移动的对象,T&&函数返回值,移动返回值,转换为T&&的函数返回值.

第2行,T&&k=getVar();

右值是匿名的,只能通过&&引用,此临时值通过&&续命,和k生命期一样长.
代码如下:

#include <iostream>
using namespace std;

int g_constructCount=0;
int g_copyConstructCount=0;
int g_destructCount=0;
struct A
{
    A(){
        cout<<"construct: "<<++g_constructCount<<endl;    
    }
    
    A(const A& a)
    {
        cout<<"copy construct: "<<++g_copyConstructCount <<endl;
    }
    ~A()
    {
        cout<<"destruct: "<<++g_destructCount<<endl;
    }
};

A GetA()
{
    return A();//这里(构造一次,拷贝构造一次)
}

int main() {
    A a = GetA();//(复制构造),第一次
    A&&a = GetA();//第二次,改成右值引用
    //也可以
	//常量左值引用
	const A& a = GetA();//
    return 0;
}

暂时这样.想把csdn的上面头给去掉下固定.结果不行.下面又有个遮罩了.
搞不了.
优化后,但不是标准.
因为常量左值引用是一个“万能”的引用类型,可以接受左值、右值、常量左值和常量右值。
但不能这样A& a = GetA();,因为非常量左值不能引用右值
第一个特点:延长寿命,本来是个临时值,,寿命延长.
第二个特点:右值引用独立于左值和右值。意思是右值引用类型的变量可能是左值也可能是右值
int&& var1 = 1;,变量1类型为右值引用,但本身是左值

template<typename T>
void f(T&& t);
f(10); //t是右值
int x = 10;
f(x); //t是左值

T&&表示的值类型不确定,可能是左值又可能是右值,右值引用的特点。
第三个特点:
T&& t在发生自动类型推断的时候,它是未定的一般引用(universal references),如果被左值初始化,它就是一个左值;如果它被一个右值初始化,它就是一个右值,它是左值还是右值取决于它的初始化。
仅当发生自动类型推导时才是.如下:

template<typename T>
void f(T&& param); //一般引用,要发生参数推导.

template<typename T>
class Test {
    Test(Test&& rhs); //右值引用.这是确定类型.主要用于移动.
};

引用折叠:
&&+&&=&&
其余:&+&,&+&&,&&+&,=>都是&.

第三行T(T&&a):m_val(val){ a.m_val=nullptr;}

移动语义来了.将右值引用作为构造函数的参数.

class A
{
public:
    A():m_ptr(new int(0)){cout << "construct" << endl;}
    A(const A& a):m_ptr(new int(*a.m_ptr)) //深拷贝的拷贝构造函数
    {
        cout << "copy construct" << endl;
    }
        A(A&& a) :m_ptr(a.m_ptr)//`是确定的右值引用类型`
    {//增加一个移动语义,调用移动构造,就没必要再生成,再释放临时对象了.
        a.m_ptr = nullptr;
        cout << "move construct" << endl;
    }//构造函数只能接受右值参数,而函数返回值是右值,就匹配到这个构造函数。
    ~A(){ delete m_ptr;}
private:
    int* m_ptr;
};
int main() {
    A a = GetA();
    return 0;
}
输出:
construct
copy construct
copy construct

带堆内存的类(必须要有深拷贝构造),默认为浅拷贝,但深拷贝有时,没必要.如果没(深拷贝),会产生悬挂指针.一是临时右值析构,二外面的a对象析构.这个时候,就可以移动语义,将所有权转义给a.
移动不行时,还得有构造函数做为基础
对普通左值进行优化,也可以移动

{
    std::list< std::string> tokens;
    //省略初始化...
    std::list< std::string> t = tokens; //这里存在拷贝 
}
std::list< std::string> tokens;
std::list< std::string> t = std::move(tokens);  //这里没有拷贝

移动将左值转换为右值引用,变成临时值,避免拷贝,提高性能
move对于含资源(堆内存或句柄)的对象来说更有意义。

第四行,完美转发,template void f(T&& val){ foo(std::forward(val)); }

template <typename T>
void forwardValue(T& val)
{
    processValue(val); //右值参数会变成左值 
}
template <typename T>
void forwardValue(const T& val)
{
    processValue(val); //参数都变成常量左值引用了 
}
//可以了.
void processValue(int& a){ cout << "lvalue" << endl; }
void processValue(int&& a){ cout << "rvalue" << endl; }
template <typename T>
void forwardValue(T&& val)
{
    processValue(std::forward<T>(val)); //照参数本来的类型进行转发。
}
void Testdelcl()
{
    int i = 0;
    forwardValue(i); //传入左值 
    forwardValue(0);//传入右值 
}
输出:
lvaue 
rvalue

结合完美转发,创建工厂函数.

template<typename...  Args>
T* Instance(Args&&... args)
{
    return new T(std::forward<Args >(args)...);
}

总之右值引用,就是引用个没有名字的临时变量.右值引用==临时变量.
用来合理利用已产生的废物的.
官方结语:完美转发,移动语义,优化性能
实现就是:静转<T&&>,将T/T&/T&&转为T&&,这样就是右值引用了.右值引用就是个废物利用.