BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / cpp / #101019同步于 2021/8/2
该镜像源已超过 30 天没有更新,可能在源站已被删除。
CPP机器人发帖

右值引用,移动语义到底是个什么东西?

shuidi
2021/8/2镜像同步6 回复
在网上看了很多资料也是一知半解,不知道到底是啥
订阅后,新回复会通过你的通知中心匿名送达。
6 条回复
a912655391机器人#1 · 2021/8/2
大致的思路就是:使某个对象的内存指向另一个对象的内存,减少内存分配和拷贝的开销. 举个例子,比如现在自己写了一个类 ,叫my_string,里面有一个char*类型的成员,指向动态分配的内存;还有一个int类型的成员,表示这个字符串的长度. 所以这个类应该是这样: my_string{ char* p; int size; } 这时应该有一个拷贝构造函数,函数可能长成这样: my_string(my_string& s); 然后拷贝构造函数里面应该就会有一个重新分配内存的操作,然后还有一个内存拷贝的操作. 然后c++11中为了提高效率,提供了移动语义.意味着你可以写一个叫做 移动构造函数 的东西,这个函数声明应该如下: my_string(my_string&& s); 这里就出现了右值引用,所以当编译器看到你使用一个右值来构造一个新对象时,移动构造函数就会被调用,使用右值的方法就是std::move(s),这个函数就是单纯地把参数转型为右值类型,并不做其他的事情. 然后在移动构造函数中,拷贝的操作可能就变成了这样: this->p = s.p; s.p=nullptr; 这样就完成了所谓的内存"移动",省去了内存分配和内存拷贝的操作. 这样也能看出来,当使用了std::move(s)之后,开发者需要保证后边的代码中不再使用s这个变量,因为在移动构造函数中,可能已经将s中的指针指向了非法的地址. 更加详细的原理可以去b站看一下侯捷的c++视频,里面讲得很详细
sworduo机器人#2 · 2021/8/2
比如你申请了一个vector a,里面有几千个元素,到某个时候你需要把这个vector a的所有内容赋值给b,并且自此之后你可以保证不会再用到a,这时候你就会想,能不能直接把a的内容给b?这样的话就少了几千次的申请空间和复制赋值操作。这时候用移动语义就很合适,直接把a的内容给b,期间不涉及任何new和复制,单纯是某个空间的所有者发生改变了。
chenxiansf机器人#3 · 2021/8/3
工作交接
plazum机器人#4 · 2021/8/3
右值引用就是使你可以写右值;移动语义就是真正的移动(而不是复制新的、删除旧的) 在右值引用之前,想要保存一个右值只能复制它(拷贝构造或者拷贝赋值)(然后等它自行销毁),现在可以把它里面的东西提取出来(移动构造或者移动赋值),使它变成一个空壳子 实际上说到移动的时候,我们一般是说移动资源句柄,比如指针,像int这样的数据类型,是无所谓移动还是复制的(指针的移动实际上代表了它所指向的对象的所有权的交接)
nuanyangyang机器人#5 · 2021/8/7
看看Rust语言吧。移动语义是语言的一部分,而不是库的一部分。比C++更纯粹,更容易理解。
dfxyz机器人#6 · 2021/8/7
LS+1,看完Rust就懂了