gpt4 book ai didi

struct - 如何为&Struct实现Default?

转载 作者:行者123 更新时间:2023-12-03 11:40:57 24 4
gpt4 key购买 nike

在阅读了很多使用rust 的书之后,我认为我已经开始了解生命周期的要点,但是对我来说,另一个问题是我们需要使用语法来声明它们。我发现这确实违反直觉。
我在这对结构上简化了我的愚蠢代码(一个引用另一个)。

#[derive(Debug, Default)]
pub struct TestStructA {
pub byte_1: u8,
pub byte_2: u8,
pub vector: Vec<u8>,
}

impl<'a> Default for &'a TestStructA {
fn default() -> &'a TestStructA {
&TestStructA { byte_1: 10, byte_2: 20, vector: 'a vec![1, 2, 3] }
}
}

#[derive(Debug, Default)]
pub struct TestStructB<'a> {
pub test_array: &'a [u8],
pub t_a: &'a TestStructA,
}
如果将此隔离的代码复制并粘贴到main.rs文件中并进行编译,则将出现以下错误:
error: expected `while`, `for`, `loop` or `{` after a label
--> src/main.rs:10:59
|
10 | &TestStructA { byte_1: 10, byte_2: 20, vector: 'a vec![1, 2, 3] }
| ^^^ expected `while`, `for`, `loop` or `{` after a label

error: labeled expression must be followed by `:`
--> src/main.rs:10:59
|
10 | &TestStructA { byte_1: 10, byte_2: 20, vector: 'a vec![1, 2, 3] }
| ---^^^^^^^^^^^^^
| | |
| | help: add `:` after the label
| the label
|
= note: labels are used before loops and blocks, allowing e.g., `break 'label` to them
如果不注释矢量参数的生存期,则会得到预期的结果:“检查您的生存期男孩”(这很有意义)。
error[E0515]: cannot return reference to temporary value
--> src/main.rs:10:9
|
10 | &TestStructA { byte_1: 10, byte_2: 20, vector: vec![1, 2, 3] }
| ^-------------------------------------------------------------
| ||
| |temporary value created here
| returns a reference to data owned by the current function
当然,如果我选择一个更严格的解决方案来从我的结构中删除“vector”属性,因为所有其他属性都是标量,则代码会编译。但是我需要我的结构具有某种非标量数据结构。我怀疑我的默认初始化程序中的向量需要某种生命周期标签,但我不确定是什么
顺便说一句,我认为我的 TestStructB也正确地标注了生命周期,但也许没有。看起来正确吗?
最后,我到达这里是因为编译器说我需要为原始结构的引用(&)版本声明一个Default初始化程序。这个原始结构已经在我的程序中愉快地使用过,但是从未被引用过。每当我开始以引用方式使用它时,Rust都声称它需要其Default初始化程序。问题是,我仍然有些觉得使用引用的Struct时做错了什么,并且有一种正确的方法来使用&referenced(且带有生命周期注释)的结构,而Rust不会提示它们的(不存在的)默认初始化器。
编辑:@JohnKugelman绝对是正确的,在典型的新手与rust编译器进行斗争以试图克服它产生的主要隐秘消息之后,我就谈到了这种“畸变”。
我的简化原文是:
#[derive(Debug, Default)]
pub struct TestStructA {
pub byte_1: u8,
pub byte_2: u8,
pub vector: Vec<u8>,
}

#[derive(Debug, Default)]
pub struct TestStructB<'a> {
pub test_array: &'a [u8],
pub t_a: &'a TestStructA,
}
有了这段代码,我得到的错误是:
error[E0277]: the trait bound `&TestStructA: Default` is not satisfied
--> src/main.rs:11:5
|
11 | pub t_a: &'a TestStructA,
| ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&TestStructA`
|
= help: the following implementations were found:
<TestStructA as Default>
= note: required by `std::default::Default::default`
= note: this error originates in a derive macro (in Nightly builds, run with -Z macro-backtrace for more info)
显然rustc误导了我以为我需要 &Struct默认初始值设定项?不能说...

最佳答案

出现非常规要求的原因是,您正在尝试为包含引用的Default结构实现TestStructB。在大多数情况下,Default用于具有所有拥有的值或可以某种方式为空的类型。
为了为引用Default实现&'a TestStructA,您将必须具有Default::default实现可以返回引用的类型的常量或泄漏值-基本上需要&'static TestStructA
如果向量为空,这很容易做到,因为Vec::new()const fn,因此我们可以构造TestStructA的完整编译时常数实例:

impl<'a> Default for &'a TestStructA {
fn default() -> &'a TestStructA {
static VALUE: TestStructA = TestStructA {
byte_1: 10,
byte_2: 20,
vector: Vec::new()
};
&VALUE
}
}
如果要在向量中包含一些数据,则必须使用像 once_cell 这样的惰性初始化机制才能执行vec!来分配向量的内容,然后返回对其的引用。
use once_cell::sync::Lazy;

static DEFAULT_A: Lazy<TestStructA> = Lazy::new(|| {
TestStructA {byte_1: 10, byte_2: 20, vector: vec![1, 2, 3]}
});

impl<'a> Default for &'a TestStructA {
fn default() -> &'a TestStructA {
&DEFAULT_A
}
}
如果要执行此操作,我建议您也实现Default for TestStructA,因为对于引用有Default而不是拥有的值很奇怪。
impl Default for TestStructA {
fn default() -> TestStructA {
DEFAULT_A.clone()
}
}
(这仅在TestStructA也实现Clone的情况下有效,但可能应该这样做。如果不这样做,则将struct文字放入TestStructA::default方法中,并将DEFAULT_A定义为Lazy::new(TestStructA::default)。)
但是,所有这些详细信息仅是必要的,因为
  • 您正在为Default
  • 实现TestStructB
  • 始终包含对TestStructA的引用。

  • 您应考虑在默认情况下TestStructB是否实际上需要此引用-例如,如果t_a的类型为Option<&'a TestStructA>,则它可以默认为None。我没有足够的信息来说明这是否适合您的应用程序-根据这些结构的确切用途做出自己的选择。

    关于struct - 如何为&Struct实现Default?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66609014/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com