C++中右值引用与移动语义的方法是什么
今天小编给大家分享一下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::endlnamespace 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++中右值引用与移动语义的方法是什么”这篇文章的所有内容,感谢各位的阅读!相信大家阅读完这篇文章都有很大的收获,小编每天都会为大家更新不同的知识,如果还想学习更多的知识,请关注编程网行业资讯频道。
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341