温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

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

发布时间:2023-03-31 11:16:40 来源:亿速云 阅读:149 作者:iii 栏目:开发技术

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

    输出

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

    以上就是“C++中右值引用与移动语义的方法是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注亿速云行业资讯频道。

    向AI问一下细节

    免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

    c++
    AI