作者littleshan (我正在想要换什麽)
看板C_and_CPP
标题Re: [问题] 右值引用的背後原理或如何达到的
时间Tue Jul 26 00:57:45 2016
※ 引述《Clangpp (Clang++)》之铭言:
: 利用move来减少复制一份的成本
: 但是我想问背後的到底是怎麽达到的??
: 要去研究编译器的行为
丑话先说在前头
move 对 POD type 来说并不会变快
得益的只有掌握资源的 class type
比如说 string、vector 等等
这类 class 在建构时会配置记忆体或其它种类的资源
因此在复制时必须使用 deep copy 以确保资源不会重覆释放
以 string 来说,假设 a, b 都是 string class,
然後我们写 a = b 时
设计 string class 的人知道我们不能放任 C++ 直接复制指向字元阵列的指标
这样当 a 与 b 都解构时会造成 double delete
因此他会在 copy assignment 中另外配置记忆体并且把资料完整复制
执行完 a = b 之後,a 和 b 都是完整而且内容相同的 string 物件
但是当你写 a = move(b) 时
意思是「我不会再使用 b 了,把 b 拥有的资源原封不动转移到 a」
执行结束後 a 拥有 b 的资源,但是 b 的内容则是 unspecified
你唯一能做的事是使用 b = XXX 来让他拥有别的内容
因此在实作 move assignment 时,只需要直接把 b 的阵列指标以及长度丢给 a
然後把 b 设定成没有内容的状态即可
做这些事不需要另外配置记忆体也不需要复制内容,自然比 copy assignment 还要快
: 问题2
: 为什麽我目前看到好像没有其他语言做这件事情??
: 像这相关的东西要如何了解??
: 谢谢
具备 move semantics 的语言并不算少见
rust 的自订型别包括 enum 与 struct
预设情况下「只有」move assignment
而且会在 compile time 把错误使用物件的情况抓出来
比如说你写
let a = String::from("abc"); // a 是字串 "abc"
let b = a; // 相当於 b = std::move(a)
let c = a; // 相当於 c = std::move(a)
这时候 compiler 会报错,然後跟你说在 b = a 之後 a 已经失去资源,
因此没办法再 move 到 c 上面
当然你可以为自订型别添加 copy assignment
那麽用起来就会比较接近 int float 之类的内建型别
另外 d language 的 struct 并没有所谓的 copy constructor
取而代之的是个称为 postblit function 的东西
当你在 d 里面复制一个 struct object 时
compiler 会先把 struct 所有栏位复制一份到新的 object 上
接着在新的 object 上呼叫 postblit function
它的任务是确保资源处在正确的 state 上
因此,对 POD 来说,postblit 就是什麽事都不用做,
而对其它拥有资源的 struct,postblit 就是依照原本的内容制作复本
或是增加 reference count
最後,compiler 的最佳化会消除没有必要的 postblit call
比如说若 compiler 发现 postblit 後紧接着另一个同样的物件会解构
那麽这个 postblit 与解构式会同时被消除掉
这就相当於节省了一次复制
D lang 的 postblit 比 C++ 的 rvalue 要简化许多
而代价就是 struct 内的栏位不能够包含指向同物件内其它栏位的指标
否则在上面消除 postblit 与解构式之後,执行结果可能会错误
主流的 OOP 语言如 C# 与 Java,物件通常都是 reference type
因为复制 reference 相当快速,因此自然是不需要 move semantics
而 C# 虽然有 struct,但是它没有 destructor,只能当 POD 使用
因此也不需要 move semantics (对POD来说没差)
最後,functional language 通常变数都是 immutable type
immutable type 同样具备复制非常快的特性 (也是只要复制 reference 呵呵)
所以它们通常也不需要 move semantics
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 1.160.83.142
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1469465868.A.A4C.html
1F:推 Caesar08: 推 07/26 01:02
2F:推 james732: 推 07/26 01:06
3F:推 LPH66: 推 07/26 01:12
4F:推 Frozenmouse: 推 07/26 07:36
5F:推 Clangpp: 推 真的太感谢了!!! 07/26 07:59
6F:推 Ebergies: 推 呵呵 07/26 09:09
7F:推 shadow0326: 今天又学到了新东西 07/26 10:30
8F:推 lc85301: 推一个 07/26 20:39
9F:推 easyman: 太强了 07/26 21:35
10F:推 ko27tye: 推 07/27 01:27
11F:推 BlazarArc: 推 07/27 21:02
12F:推 Sidney0503: 推 07/30 17:55