如何返回对全局向量或内部选项的引用?

3
我想创建一个可以返回到常量全局数组或项目中的Data引用的方法。生命周期肯定不同,但可以安全地假设数据的生命周期至少与项目的生命周期一样长。在此过程中,我希望编译器在我出错时发出警告,但它会生成错误的指令,导致程序崩溃并显示SIGILL
具体来说,在Rust 1.27.2中,以下代码失败:
#[derive(Debug)]
pub enum Type {
    TYPE1,
    TYPE2,
}

#[derive(Debug)]
pub struct Data {
    pub ctype: Type,
    pub int: i32,
}

#[derive(Debug)]
pub struct Entity {
    pub idata: usize,
    pub modifier: Option<Data>,
}

impl Entity {
    pub fn data(&self) -> &Data {
        if self.modifier.is_none() {
            &DATA[self.idata]
        } else {
            self.modifier.as_ref().unwrap()
        }
    }
}

pub const DATA: [Data; 1] = [Data {
    ctype: Type::TYPE2,
    int: 1,
}];

fn main() {
    let mut itemvec = vec![Entity {
        idata: 0,
        modifier: None,
    }];
    eprintln!("vec[0]: {:p} = {:?}", &itemvec[0], itemvec[0]);
    eprintln!("removed item 0");
    let item = itemvec.remove(0);
    eprintln!("item: {:p} = {:?}", &item, item);
    eprintln!("modifier: {:p} = {:?}", &item.modifier, item.modifier);
    eprintln!("DATA: {:p} = {:?}", &DATA[0], DATA[0]);
    let itemdata = item.data();
    eprintln!("itemdata: {:p} = {:?}", itemdata, itemdata);
}

完整代码

我不明白我做错了什么。为什么编译器没有生成警告?是因为向量中的(非复制)项被删除了吗?还是存在歧义的生命周期?


1
你可能想使用 static 而不是 const。实际上它们可能是相同的,但是 static 保证了你可能想要的行为:只有一个 DATA 数组,所有引用都指向它的内部。 - trent
1个回答

4
如何返回全局向量或内部Option的引用?使用 Option::unwrap_or_else 方法:
impl Entity {
    pub fn data(&self) -> &Data {
        self.modifier.as_ref().unwrap_or_else(|| &DATA[self.idata])
    }
}

但它却生成了错误的指令,程序崩溃并显示 SIGILL 错误。在macOS上使用Rust 1.27.2或1.28.0时,您提供的代码不会出现这种情况。在Ubuntu上,当在Valgrind中运行程序时会出现问题,但在Rust 1.28.0中问题会消失。
另请参见:

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