«

C++中右值引用与移动语义的方法是什么

时间:2024-7-19 11:03     作者:韩俊     分类: Java


今天小编给大家分享一下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();
    }

    输出

    标签: java

    热门推荐