首页 文章

在Rust中移动语义

提问于
浏览
2

我在Rust中包装一个C库,它的许多函数通过指向结构的指针来获取参数,这些结构本身通常具有指向其他结构的指针 . 为了减少开销,我想提供将Rust数据编组的结果缓存到C结构中的能力 .

以下是C库如何期望某些参数的示例:

#[repr(C)]
struct Foo {
    x: i32,
    y: f32
}

#[repr(C)]
struct Bar {
    p_foo: *const Foo,
    z: bool
}

我怎么想象一个拥有的“缓存”版本看起来:

struct Cached {
    foo: Option<Foo>,
    bar: Bar
}

barp_foo 字段将被构造为指向 foo 中的 Some 值,或者如果存在 None 则指向空指针 .

当然,问题在于,如果要移动 Cached 的值,则直接 memcpy 将是不合适的,并且还需要重定向 bar.p_foo . 这很容易用C语言确定,具有可定义的移动语义,但Rust除了提供一个解决方案之外“不设置 bar.p_foo ,直到它想象这些缓存的值将被移动超过(甚至接近频率) )它们被重用,并且有一些工作涉及设置这些指针,特别是如果嵌套/链接很深/很长 . 我也不愿意在堆上的子结构中使用.2860352_ .


为了澄清,这里是我可以用C编写的内容,我想在Rust中复制:

struct Foo {
    int x;
    float y;
};

struct Bar {
    Foo const*pFoo;
    bool z;
};

// bear with me while I conjure up a Maybe for C++
class Cached {
public:
    // would have appropriate copy constructor/assignment

    Cached(Cached &&other) {
        m_foo = other.m_foo;
        m_bar = other.m_bar;

        if(m_foo.isJust()) {
            m_bar.pFoo = &m_foo.value();
        } // else already nullptr
    }

    // similar move assignment

private:
    Maybe<Foo> m_foo;
    Bar m_bar;
};

1 回答

  • 1

    Rust等效的是不使用原始指针,因为原始指针用于实现我们的安全数据结构,而不是用于实现普通数据结构 .

    #[repr(C)]
    struct Foo {
        x: i32,
        y: f32
    }
    
    #[repr(C)]
    struct Bar {
        p_foo: Option<Box<Foo>>,
        z: bool
    }
    

    只要 T 是一个类型而不是特征, Option<Box<T>> 保证与 *const T 完全等效(在内存中的位) . 唯一的区别是它在Rust中使用是安全的 .

    这样你甚至不再需要 Cached 结构,但可以直接传递 Bar 对象 .


    我也不愿意在堆上装箱子结构 .

    然后我建议你不要保留一个 Bar 对象,而是在需要将一个传递给C时召唤它:

    #[repr(C)]
    struct Foo {
        x: i32,
        y: f32
    }
    
    #[repr(C)]
    struct Bar<'a> {
        p_foo: Option<&'a Foo>,
        z: bool
    }
    
    struct Cached {
        foo: Option<Foo>,
        z: bool,
    }
    
    impl Cached {
        fn bar<'a>(&'a self) -> Bar<'a> {
            Bar {
                p_foo: self.foo.as_ref(),
                z: self.z,
            }
        }
    }
    

    设置这些指针需要做一些工作,特别是如果嵌套/链接很深/很长 .

    这听起来很像过早的优化 . 不要优化您没有基准的位置 .

相关问题