Re: [问题] 右值引用的背后原理或如何达到的

楼主: littleshan (我要加入剑道社!)   2016-07-26 00:57:45
※ 引述《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
作者: Caesar08 (Caesar)   2016-07-26 01:02:00
作者: james732 (好人超)   2016-07-26 01:06:00
作者: LPH66 (-6.2598534e+18f)   2016-07-26 01:12:00
作者: Frozenmouse (*冰之鼠*)   2016-07-26 07:36:00
作者: Clangpp (Clang++)   2016-07-26 07:59:00
推 真的太感谢了!!!
作者: Ebergies (火神)   2016-07-26 09:09:00
推 呵呵
作者: shadow0326 (非议)   2016-07-26 10:30:00
今天又学到了新东西
作者: lc85301 (pomelocandy)   2016-07-26 20:39:00
推一个
作者: easyman (oops)   2016-07-26 21:35:00
太强了
作者: ko27tye (好滋好滋)   2016-07-27 01:27:00
作者: BlazarArc (Midnight Sun)   2016-07-27 21:02:00
作者: Sidney0503 (Sidney0503)   2016-07-30 17:55:00

Links booklink

Contact Us: admin [ a t ] ucptt.com