-
Notifications
You must be signed in to change notification settings - Fork 172
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[第五章]clone方法按位复制概念错误 #75
Comments
@kvinwang 感谢反馈。这个地方我再继续仔细斟酌一下,看看怎么把它描述的更加清晰精准。 |
P121页
这个描述是对按位复制的误解,需要修正。以及修正章节中对「栈复制」和「按位复制」混乱使用的问题。 读者按照「按位复制」的理解是没有问题的。 |
这句话不只“按位复制就是指栈复制”一点问题哦,和浅复制、深复制对应起来也是不对的。 |
@kvinwang 是的,这句话是要修正的更加精准 |
根据官方文档, Copy 类型的 clone 实现应该是 trivial 的:
同时, Copy 类型的语义就是按位拷贝:
如果 clone 和 copy 行为不一致,即违反了标准库约定的语义。 |
@mzji 嗯,现在主要问题是通用概念里「按位拷贝」、「栈拷贝」、「浅复制」和「深复制」没有说清楚。 |
主要是说明
这里的第一点的括号内的部分和第二点是有问题的 之前我看过一些材料,提到过说对于 Copy 类型,调用它的 clone 方法会直接被编译器优化成按位拷贝 至于栈拷贝,不建议再提这个概念了,不是很重要 |
至于浅复制和深复制,更多的只和包含堆存储的类型相关,如果展开描述时也应注意这一点 |
首先“应该"并不代表"必须", 凡是必须的,都应该是编译器来保证。如果必须,Rust完全可以禁止Copy类型自定义实现clone,因为必须一致嘛,自定义就没有意义了。
即便我们遵从”应当“,文档的意思比较模糊,写文档的人应该没考虑到这里的表意有些不妥。 struct A(i8);
impl Copy for A {}
impl Clone for A {
fn clone(&self) -> A {
A(self.0)
}
} 我认为这样实现并没有什么问题,但是它已经不是
当然不是UB,凡是safe rust出现UB,都属于bug。 |
这里引用的原文, should 应当理解为 must 。
至于那个例子是否算是“应当”,只看它满不满足判断标准即可
也即 clone 的结果应当与按位拷贝一致。 |
@kvingwang 追求严谨 |
|
unsafe code 不允许依赖于此行为又没啥问题,因为总可以用按位拷贝语义。 |
已找到官方文档对这一点的描述: RFC 1521: Copy Clone semantics
因此修正我的观点,应当是“clone 的结果”与按位拷贝一致,没有约束具体实现。这样可以方便 rustc 将 Copy 类型的 clone 优化为按位拷贝(因为结果一致)。
其他相关资料: |
@mzji 谢谢你的资料。这些资料里大量使用了should。
也就是说允许存在一些特殊场景不遵守这个约定。 |
按照定义来说确实如此,不过考虑到实现的语义我还是建议做一个 trivial 的实现,这样便于优化。 |
感觉越描越黑了,Copy类型"赋值"时就是按位复制,"浅复制"等其它概念我明天在另一个issue里面举例说明一下吧 |
Rust 本身没怎么提到深复制和浅复制,大多是时候只是强调 Copy 类型和 Move 类型之间的区别,最多说一句 clone 行为可自定,多了都没提 |
@ZhangHanDong 我在 #77 里面给了些我的理解,还是觉得没必要强行关联理解。 |
@kvinwang 辛苦了。 |
我认为是 Rust 有意淡化之前的浅拷贝和深拷贝的概念 |
同意 |
合并到这个issues讨论: 对书中值语义、引用语义、栈拷贝、按位复制等概念的澄清 |
@kvinwang 感谢 |
页码与行数
实际上
--- edit ----
PS. Copy也不一定用于栈拷贝, 比如:
The text was updated successfully, but these errors were encountered: