C++学习笔记(五十):c++ 移动语义与std::move

本节介绍c++的移动语义与新特性std::move,本节介绍的内容主要用在性能优化上。

c++移动语义和c++左值右值的内容相关联,可以先看之前发的左值右值内容。

不使用移动语义的代码如下:

#include <iostream>
class String
{
public:
	String() = default;
	String(const char* date)
	{
		std::cout << "Created!\n";
		m_Data = new char[strlen(date)+1];
		m_Size = strlen(date);
		memcpy(m_Data, date, m_Size+1);
	}
	String(const String& other)
	{
		std::cout << "Copityed!\n";
		m_Data = new char[other.m_Size + 1];  //需要在堆上分配,所以会影响性能,移动语义可以不在堆上进行分配
		m_Size = other.m_Size;
		memcpy(m_Data, other.m_Data, m_Size + 1);

	}

	~String()
	{
		delete[] m_Data;
	}
	void PrintString()
	{
		for (int i = 0; i < m_Size; i++)
		{
			std::cout << m_Data[i];
		}
		std::cout << "\n";

	}
private:
	char* m_Data;
	uint32_t m_Size;
};
class Entity
{
public:
	Entity(const String& name)
		:m_Name(name)
	{}
	void Print()
	{
		m_Name.PrintString();
	}
private:
	String m_Name;
};

int main()
{
	Entity entity(String("pcop"));
	entity.Print();

	std::cin.get();
}

上述代码执行结果如下:

Created!
Copityed!
pcop

可以看到执行了两次内存分配,一次是在Created中,一次是在Copityed中,因为String("pcop")先创建了一个String对象,然后通过引用的方式传递给Entity,Entity调用复制构造函数,在复制构造函数中新建一个String对象m_Data。

使用移动语义,可以减去String("pcop")创建String对象这一次内存分配,代码如下:

#include <iostream>
class String
{
public:
	String() = default;
	String(const char* date)
	{
		std::cout << "Created!\n";
		m_Data = new char[strlen(date)+1];
		m_Size = strlen(date);
		memcpy(m_Data, date, m_Size+1);
	}
	String(const String& other)
	{
		std::cout << "Copityed!\n";
		m_Data = new char[other.m_Size + 1];  //需要在堆上分配,所以会影响性能,移动语义可以不在堆上进行分配
		m_Size = other.m_Size;
		memcpy(m_Data, other.m_Data, m_Size + 1);

	}
	String(String&& other) noexcept //传递的是一个右值,临时值
	{
		std::cout << "Moved!\n";
		m_Data = other.m_Data;     //实际进行了一次浅拷贝,m_Data指针指向other.m_Data所指的内存地址
		m_Size = other.m_Size;
		other.m_Size = 0;
		other.m_Data = nullptr;
	}

	~String()
	{
		std::cout << "Destroyed!\n";
		delete[] m_Data;
	}
	void PrintString()
	{
		for (int i = 0; i < m_Size; i++)
		{
			std::cout << m_Data[i];
		}
		std::cout << "\n";

	}
private:
	char* m_Data;
	uint32_t m_Size;
};
class Entity
{
public:
	Entity(const String& name)
		:m_Name(name)
	{}
	Entity(String&& name)
		:m_Name((String&&)name)  
	{}
	void Print()
	{
		m_Name.PrintString();
	}
private:
	String m_Name;
};

int main()
{
	Entity entity(String("pcop"));
	entity.Print();

	std::cin.get();
}

std::move的使用方式及移动赋值运算符,代码如下:

#include <iostream>
class String
{
public:
	String() = default;
	String(const char* date)
	{
		std::cout << "Created!\n";
		m_Data = new char[strlen(date)+1];
		m_Size = strlen(date);
		memcpy(m_Data, date, m_Size+1);
	}
	String(const String& other)
	{
		std::cout << "Copityed!\n";
		m_Data = new char[other.m_Size + 1];  //需要在堆上分配,所以会影响性能,移动语义可以不在堆上进行分配
		m_Size = other.m_Size;
		memcpy(m_Data, other.m_Data, m_Size + 1);

	}
	String(String&& other) noexcept //传递的是一个右值,临时值
	{
		std::cout << "Moved!\n";
		m_Data = other.m_Data;     //实际进行了一次浅拷贝,m_Data指针指向other.m_Data所指的内存地址
		m_Size = other.m_Size;
		other.m_Size = 0;
		other.m_Data = nullptr;
	}
	String& operator=(String&& other) noexcept
	{
		std::cout << "Moved!\n";
		if (this != &other)
		{
			delete[] m_Data;
			m_Data = other.m_Data;     //实际进行了一次浅拷贝,m_Data指针指向other.m_Data所指的内存地址
			m_Size = other.m_Size;
			other.m_Size = 0;
			other.m_Data = nullptr;
		}
		return *this;

	}

	~String()
	{
		std::cout << "Destroyed!\n";
		delete[] m_Data;
	}
	void PrintString()
	{
		for (int i = 0; i < m_Size; i++)
		{
			std::cout << m_Data[i];
		}
		std::cout << "\n";

	}
private:
	char* m_Data;
	uint32_t m_Size;
};
class Entity
{
public:
	Entity(const String& name)
		:m_Name(name)
	{}
	Entity(String&& name)
		:m_Name(std::move(name))  
	{}
	void Print()
	{
		m_Name.PrintString();
	}
private:
	String m_Name;
};

int main()
{
	//Entity entity(String("pcop"));
	//entity.Print();

	String s1 = "pcop";
	//String s2 = std::move(s1);  //使用move将s1转换成临时变量,此时=调用的是构造函数,而不是移动赋值运算符

	String s3;
	s3 = std::move(s1);  //此时调用的是移动赋值运算符

	s3.PrintString();

	std::cin.get();
}

相关推荐

  1. C++学习笔记):c++ 移动语义std::move

    2024-01-27 23:10:03       31 阅读
  2. C++学习笔记(二):c++ 智能指针

    2024-01-27 23:10:03       36 阅读
  3. C#(C Sharp)学习笔记_类【

    2024-01-27 23:10:03       11 阅读
  4. C++学习笔记

    2024-01-27 23:10:03       31 阅读
  5. C++11,移动语义

    2024-01-27 23:10:03       38 阅读
  6. C++移动语义

    2024-01-27 23:10:03       8 阅读
  7. C++学习笔记一)

    2024-01-27 23:10:03       36 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-27 23:10:03       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-27 23:10:03       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-27 23:10:03       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-27 23:10:03       20 阅读

热门阅读

  1. 设计模式---观察者模式

    2024-01-27 23:10:03       32 阅读
  2. cs2系统提升思路

    2024-01-27 23:10:03       37 阅读
  3. 从k8s当中学习go cli脚手架开发利器-cobra

    2024-01-27 23:10:03       33 阅读
  4. 一篇文章带你全面理解热更新技术

    2024-01-27 23:10:03       32 阅读
  5. Golang 垃圾回收

    2024-01-27 23:10:03       32 阅读