正如我所读到的,D中的所有对象都是完全独立于位置的。如何实现这一要求?
我想到的一件事是,所有引用都不是指向对象的指针,而是指向某些代理,因此当您移动对象(在内存中)时,您只需更新该代理,而不是程序中使用的所有引用。 / p>
但这只是我的猜测。它是如何在D中完成的?
答案 0 :(得分:5)
编辑:前面的底线,没有代理对象,通过常规指针直接引用对象。 /编辑
结构体不允许保留指向自己的指针,所以如果它们被复制,它们应该继续正常工作。尽管如此,这并没有严格执行:
struct S {
S* lol;
void beBad() {
lol = &this; // this compiler will allow this....
}
}
S pain() {
S s;
s.beBad();
return s;
}
void main() {
S s;
s = pain();
assert(s.lol !is &s); // but it will also move the object without notice!
}
(编辑:实际上,我猜你可以使用postblit来更新内部指针,所以它没有通知。如果你足够小心,你可以让它工作,但话又说回来,如果你足够小心,你也可以在你的脚趾之间射击而不会碰到你的脚。编辑2:实际上没有,编译器/运行时仍然允许移动它甚至没有调用postblit。发生这种情况的例子是,如果它将堆栈帧复制到堆中以进行闭包。结构数据被移动到新地址而不被通知。所以是的./ edit)
实际上,断言不能保证通过,编译器可能会选择直接在pain
中声明的本地对象上调用main
,所以指针可以工作(虽然我不能在这里为演示强制进行这种优化,一般来说,当你从一个函数返回一个结构时,它实际上是通过调用者传递的隐藏指针完成的 - 调用者说&#34 ;将返回值放在这里"因此在某些情况下避免复制/移动。)
但是,无论如何,重点是编译器可以自由地复制或不复制结构,所以如果你确实保留了它的地址,它可能会在没有通知的情况下变为无效;保持该指针不是编译错误,但它是未定义的行为。
情况与班级不同。类是允许在内部保持对this
的引用,因为类(理论上,通过垃圾收集器实现实现))具有无限生存期的独立对象。虽然它可能被移动(例如移动GC(今天未在D中实现)),但如果移动它,则所有对它的引用(内部和外部)也都需要更新。
因此,类不能像结构一样将内存从它们下面拉出来(除非程序员自己动手并绕过GC ......)
与位置无关的事情我非常肯定只是指结构,而只是指他们不能指向自己的规则。引用或指针没有神奇的功能 - 它们确实适用于内存地址,没有代理对象。