今天小编给大家分享一下C++中右值引用与移动语义的方法是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。
意义
充分利用临时对象,避免拷贝。
左值右值
值类别
在 C++11之后,C++根据
被标识:可通过不同标识符指代同一实体。(对象/内存)
可移动:可作为移动语义函数的参数,例如移动构造,移动赋值。
将值分为以下类别:
泛左值:被标识
左值:被标识且不可移动
将亡值:被标识可移动
右值:可移动
将亡值:被标识可移动
纯右值:不被标识且可移动
左值
int a = 1;
a是一个左值,左值是关联了名称的内存位置。
纯右值
int a = 1;
1是一个纯右值,纯右值是指不被标识且可移动的值,例如字面量。
将亡值
using std::string;
string get()
{
    string ret = "abc";
    return ret;
}
string str = get();get() 函数调用会产生一个临时变量赋给str,这个临时变量是将亡值,此时的赋值是移动语义(c++11之前是复制语义)。
左值引用
int a = 1; int& a_lref = a;
a_lref是左值引用
右值引用
int&& rref = 1;
rref是右值引用(rref是类型为右值引用的左值)
std::move()
void foo(int&& rref)
{
}
int a = 1;
foo(std::move(a));std::move本质是类型转换,即把左值转换成右值
注意:被转换的对象不应再被使用,否则结果难以预计(通常内存会被转移)
移动构造&移动赋值运算符重载
class Foo
{
public:
    Foo()
    {
        m_data = malloc(32);
    }
    Foo(const Foo& rhs)
    {
        if(m_data == nullptr)
        {
            m_data = malloc(32);
        }
        memcopy(m_data,rhs.m_data,32);
    }
    Foo& operator = (const Foo& rhs)
    {
        if(m_data == nullptr)
        {
            m_data = malloc(32);
        }
        memcopy(m_data,rhs.m_data,32);
        return *this;
    }
    Foo(Foo&& rhs) noexcept
    {
        m_data = rhs.m_data;
        rhs.m_data = nullptr;
    }
    Foo& operator = (Foo&& rhs) noexcept
    {
        m_data = rhs.m_data;
        rhs.m_data = nullptr;
        return *this;
    }
private:
    void* m_data
}移动构造的本质就是内存资源所有权的转移
测试&验证
#include <iostream>
#include <cstdlib>
#define LOG(Args) std::cout << "==== " << Args << " ====" << std::endl
namespace My
{
    class Vector
    {
    public:
        Vector() noexcept
        {
            LOG("Ctor");
            m_data = new int[] {0, 0, 0, };
        }
        ~Vector()
        {
            LOG("Dector");
            m_data = new int[] {0, 0, 0, };
        }
        Vector(const Vector& rhs)
        {
            LOG("Copy");
            if (m_data == nullptr)
            {
                m_data = new int[3];
            }
            memcpy(m_data, rhs.m_data, 3 * sizeof(int));
        }
        Vector& operator = (const Vector& rhs) 
        {
            LOG("Copy Operator = ");
            if (m_data == nullptr)
            {
                m_data = new int[3];
            }
            memcpy(m_data, rhs.m_data, 3 * sizeof(int));
            return *this;
        };
        Vector& operator = (Vector&& rhs) noexcept
        {
            LOG("Move Operator = ");
            m_data = rhs.m_data;
            rhs.m_data = nullptr;
            return *this;
        };
        Vector(Vector&& rhs) noexcept
        {
            LOG("Move");
            m_data = rhs.m_data;
            rhs.m_data = nullptr;
        }
        void print()
        {
            std::cout << "X = " << m_data[0] <<
                " , " << "Y = " << m_data[1] <<
                " , " << "Z = " << m_data[2] << std::endl;
        }
        void set(int x,int y,int z)
        {
            m_data[0] = x;
            m_data[1] = y;
            m_data[2] = z;
        }
    private:
        int* m_data;
    };
}
My::Vector Get()
{
    My::Vector vec;
    vec.set(4, 5, 6);
    return vec;
}
void main()
{
    My::Vector vec1;
    My::Vector vec2;
    LOG("vec1");
    vec1.print();
    vec1.set(0, 1, 2);
    LOG("vec1");
    vec1.print();
    vec1 = vec2;
    LOG("vec1");
    vec1.print();
    vec1 = std::move(vec2);
    LOG("vec1");
    vec1.print();
    My::Vector* vp1 = new My::Vector();
    LOG("vp1");
    vp1->print();
    My::Vector* vp2 = new My::Vector(*vp1);
    LOG("vp2");
    vp2->print();
    My::Vector* vp3 = new My::Vector(std::move(*vp1));
    LOG("vp3");
    vp3->print();
    My::Vector* vp4 = new My::Vector(Get());
    LOG("vp4");
    vp4->print();
}输出