在 Rust 中,当您需要引用持有结构有时拥有其引用数据时的模式是什么?
In Rust, what's the pattern for when you need a reference-holding struct to sometimes own its referenced data?
考虑以下数据结构:
struct ReferenceHoldingStruct<'a> {
pub prop: &'a str
}
这种模式通常很有用,尤其是在解析器(我的用例)中,用于“给”结构一些字符串数据而不重新分配它:
fn generate_these_1<'a>(input: &'a str) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: input }
}
但是,我有一个情况,我有一个像上面这样的结构,但在一个地方我需要生成“独立”的实例;即他们拥有自己的数据:
fn generate_these_2<'a>(input: String) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: input.as_str() }
}
我明白为什么这个版本不起作用:被引用的字符串不存在于 Rust 可以看到它会徘徊以继续实现结构的 &str
引用的任何地方。我想也许这会奏效:
fn generate_these_2<'a>(input: String) -> (String, ReferenceHoldingStruct<'a>) {
(input, ReferenceHoldingStruct { prop: input.as_str() })
}
因为至少 String 不会立即被删除。我想也许 Rust 可以弄清楚这个元组既包含引用又包含它引用的数据,因此只要它们像这样保持在一起就有效。但没有骰子:这仍然行不通。它将引用视为借用,将移动到元组视为移动,您不能“同时”执行这两项操作。
所以,我明白这个问题,但不知道从哪里开始。这种情况的标准做法是什么?
您可以存储实现 Borrow<str>
的内容:
struct ReferenceHoldingStruct<S: Borrow<str>> {
pub prop: S,
}
S
上的绑定允许它是任何可以作为 &str
借用的东西。这可能是一个 &str
本身,或一个拥有的 String
(或任何其他实现 Borrow<str>
的东西)。由于在 T
和 &T
上都有实现 Borrow<T>
的全面实现,因此这种方法可用于存储引用或拥有任何类型的值,而不仅仅是 str
.
这里有一个 Cow
的例子(在评论中提到):
use std::borrow::Cow;
struct ReferenceHoldingStruct<'a> {
pub prop: Cow<'a, str>
}
fn generate_these_1<'a>(input: &'a str) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: Cow::Borrowed(input) }
}
fn generate_these_2<'a>(input: String) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: Cow::Owned(input) }
}
考虑以下数据结构:
struct ReferenceHoldingStruct<'a> {
pub prop: &'a str
}
这种模式通常很有用,尤其是在解析器(我的用例)中,用于“给”结构一些字符串数据而不重新分配它:
fn generate_these_1<'a>(input: &'a str) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: input }
}
但是,我有一个情况,我有一个像上面这样的结构,但在一个地方我需要生成“独立”的实例;即他们拥有自己的数据:
fn generate_these_2<'a>(input: String) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: input.as_str() }
}
我明白为什么这个版本不起作用:被引用的字符串不存在于 Rust 可以看到它会徘徊以继续实现结构的 &str
引用的任何地方。我想也许这会奏效:
fn generate_these_2<'a>(input: String) -> (String, ReferenceHoldingStruct<'a>) {
(input, ReferenceHoldingStruct { prop: input.as_str() })
}
因为至少 String 不会立即被删除。我想也许 Rust 可以弄清楚这个元组既包含引用又包含它引用的数据,因此只要它们像这样保持在一起就有效。但没有骰子:这仍然行不通。它将引用视为借用,将移动到元组视为移动,您不能“同时”执行这两项操作。
所以,我明白这个问题,但不知道从哪里开始。这种情况的标准做法是什么?
您可以存储实现 Borrow<str>
的内容:
struct ReferenceHoldingStruct<S: Borrow<str>> {
pub prop: S,
}
S
上的绑定允许它是任何可以作为 &str
借用的东西。这可能是一个 &str
本身,或一个拥有的 String
(或任何其他实现 Borrow<str>
的东西)。由于在 T
和 &T
上都有实现 Borrow<T>
的全面实现,因此这种方法可用于存储引用或拥有任何类型的值,而不仅仅是 str
.
这里有一个 Cow
的例子(在评论中提到):
use std::borrow::Cow;
struct ReferenceHoldingStruct<'a> {
pub prop: Cow<'a, str>
}
fn generate_these_1<'a>(input: &'a str) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: Cow::Borrowed(input) }
}
fn generate_these_2<'a>(input: String) -> ReferenceHoldingStruct<'a> {
ReferenceHoldingStruct { prop: Cow::Owned(input) }
}