是否在D中间接访问对象?

时间:2014-03-15 19:55:16

标签: object d

正如我所读到的,D中的所有对象都是完全独立于位置的。如何实现这一要求?

我想到的一件事是,所有引用都不是指向对象的指针,而是指向某些代理,因此当您移动对象(在内存中)时,您只需更新该代理,而不是程序中使用的所有引用。 / p>

但这只是我的猜测。它是如何在D中完成的?

1 个答案:

答案 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 ......)

与位置无关的事情我非常肯定只是指结构,而只是指他们不能指向自己的规则。引用或指针没有神奇的功能 - 它们确实适用于内存地址,没有代理对象。