如何制作一个结构体,其中一个字段引用另一个字段 [英] How to make a struct where one of the fields refers to another field

查看:48
本文介绍了如何制作一个结构体,其中一个字段引用另一个字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有以下问题:我有一个从缓冲区解析的数据结构,并包含对该缓冲区的一些引用,因此解析函数看起来像

I have the following problem: I have a have a data structure that is parsed from a buffer and contains some references into this buffer, so the parsing function looks something like

fn parse_bar<'a>(buf: &'a [u8]) -> Bar<'a>

到目前为止,一切都很好.但是,为了避免某些生命周期问题,我想将数据结构和底层缓冲区放入一个结构中,如下所示:

So far, so good. However, to avoid certain lifetime issues I'd like to put the data structure and the underlying buffer into a struct as follows:

struct BarWithBuf<'a> {bar: Bar<'a>, buf: Box<[u8]>}
// not even sure if these lifetime annotations here make sense,
// but it won't compile unless I add some lifetime to Bar

然而,现在我不知道如何实际构造一个 BarWithBuf 值.

However, now I don't know how to actually construct a BarWithBuf value.

fn make_bar_with_buf<'a>(buf: Box<[u8]>) -> BarWithBuf<'a> {
    let my_bar = parse_bar(&*buf);
    BarWithBuf {buf: buf, bar: my_bar}
}

不起作用,因为 buf 在 BarWithBuf 值的构造中被移动了,但我们借用了它进行解析.

doesn't work, since buf is moved in the construction of the BarWithBuf value, but we borrowed it for parsing.

我觉得应该可以做一些类似的事情

I feel like it should be possible to do something along the lines of

fn make_bar_with_buf<'a>(buf: Box<[u8]>) -> BarWithBuf<'a> {

    let mut bwb = BarWithBuf {buf: buf};
    bwb.bar = parse_bar(&*bwb.buf);
    bwb
}

避免在解析 Bar 后移动缓冲区,但我不能这样做,因为必须一次性初始化整个 BarWithBuf 结构.现在我怀疑我可以使用 unsafe 代码来部分构造结构,但我宁愿不这样做.解决这个问题的最佳方法是什么?我需要不安全的代码吗?如果我这样做,在这里这样做是否安全?还是我在这里完全走错了路,有更好的方法将数据结构与其底层缓冲区联系在一起?

to avoid moving the buffer after parsing the Bar, but I can't do that because the whole BarWithBuf struct has to be initalised in one go. Now I suspect that I could use unsafe code to partially construct the struct, but I'd rather not do that. What would be the best way to solve this problem? Do I need unsafe code? If I do, would it be safe do to this here? Or am I completely on the wrong track here and there is a better way to tie a data structure and its underlying buffer together?

推荐答案

我认为您是对的,没有不安全的代码就不可能做到这一点.我会考虑以下两个选项:

I think you're right in that it's not possible to do this without unsafe code. I would consider the following two options:

  1. Bar 中的引用更改为索引.框内的内容不受借用保护,因此如果您不小心,索引可能会失效.但是,索引可能会以更清晰的方式传达引用的含义.

  1. Change the reference in Bar to an index. The contents of the box won't be protected by a borrow, so the index might become invalid if you're not careful. However, an index might convey the meaning of the reference in a clearer way.

Box<[u8]>移动到Bar中,并添加一个函数buf() ->&[u8]Bar 的实现;而不是引用,将索引存储在 Bar 中.现在 Bar 是缓冲区的所有者,因此它可以控制其修改并保持索引有效(从而避免选项 #1 的问题).

Move Box<[u8]> into Bar, and add a function buf() -> &[u8] to the implementation of Bar; instead of references, store indices in Bar. Now Bar is the owner of the buffer, so it can control its modification and keep the indices valid (thereby avoiding the problem of option #1).

根据下面 DK 的建议,将索引存储在 BarWithBuf(或辅助结构 BarInternal)中并添加函数 fn bar(&自我)->BarBarWithBuf 的实现,它会即时构造一个 Bar.

As per DK's suggestion below, store indices in BarWithBuf (or in a helper struct BarInternal) and add a function fn bar(&self) -> Bar to the implementation of BarWithBuf, which constructs a Bar on-the-fly.

这些选项中哪一个最合适取决于实际的问题上下文.我同意某种形式的逐个成员构造"结构在 Rust 中会非常有帮助.

Which of these options is the most appropriate one depends on the actual problem context. I agree that some form of "member-by-member construction" of structs would be immensely helpful in Rust.

这篇关于如何制作一个结构体,其中一个字段引用另一个字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆