在 Rust 中,如何显式地将两个对象的生命周期绑定在一起,而不相互引用?

4
遇到这种情况是在使用OpenGL编写VertexBufferVertexArraystruct时。每个结构实质上都是一个单独的GLuint,用于引用OpenGL对象。在最简单的情况下,VertexArray恰好与一个VertexBuffer相关联。
问题在于VertexArray的生命周期不能超过其关联的VertexBuffer。然而,Rust并不知道这一点,因为VertexArray所持有的引用是内部OpenGL的,因此它会在一个现有的VertexArray引用它的同时调用VertexBuffer上的析构函数,这样会出现问题。
我目前的解决方案是手动放置一个未使用的引用:
struct VertexArray<'a> {
    id: GLuint,
    #[warn(dead_code)]
    vbo: &'a VertexBuffer
}

在更复杂的情况下,引用可能会变得必要,但感觉不够优雅且浪费资源。具有多个VBO的VAO可以使用引用的数组/向量来实现。在创建VAO之后能够更改相关缓冲区也可能增加此要求。
是否有任何方法可以在没有引用的情况下实现相同的行为?或者,由于编译器可以识别出引用从未被使用并发出警告,因此它是否会被优化掉?
1个回答

5
这是使用PhantomData类型的主要用例之一,正如示例中所演示的那样。应用于这种情况,您将得到类似以下的内容:
use std::marker::PhantomData;

struct VertexArray<'a> {
    id: GLuint,
    vbo_lifetime: PhantomData<&'a VertexBuffer>,
}

实例化的代码将如下所示:

    fn make<'a>(&'a self) -> VertexArray<'a> {
        VertexArray {
            id: …,
            vbo_lifetime: PhantomData,
        }
    }

(这是省略了泛型类型,使其可以被推断;您也可以写成 PhantomData::<&'a VertexBuffer>。)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接