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