Rust 为什么我可以返回对一个函数所拥有的值的引用?

Rust 为什么我可以返回对一个函数所拥有的值的引用?,rust,lifetime,ownership,Rust,Lifetime,Ownership,在Rust编程语言的第19.2章中,以下示例编译时没有任何错误。我从中发现,有一个新的生存期省略规则隐式地使's比'c长 虽然我找不到这个新的省略规则的详细解释,但我猜它不仅仅是更长、更显式约束的隐式版本:(&'s str); 结构分析器 { 上下文:&'c上下文 { 错误(self.context.0) } } fn parse_context(context:context)->Result { 解析器{context:&context}.parse() } fn main() { 让mut

在Rust编程语言的第19.2章中,以下示例编译时没有任何错误。我从中发现,有一个新的生存期省略规则隐式地使
's
'c

虽然我找不到这个新的省略规则的详细解释,但我猜它不仅仅是更长、更显式约束的隐式版本:
(&'s str);
结构分析器
{
上下文:&'c上下文
{
错误(self.context.0)
}
}
fn parse_context(context:context)->Result
{
解析器{context:&context}.parse()
}
fn main()
{
让mut s=String::new();
s+=“有效”;
s+=“能吗?”;
if let Err(text)=解析上下文(上下文(&s))
{
println!(“{}”,文本);
}
}

您不是在返回对函数所属值的引用。您正在返回传入的引用的副本

您的函数是identity函数的精巧版本:

fn parse_context(s: &str) -> &str {
    s
}
在实际代码中,先引用一个包含字符串片段的结构,然后再引用另一个字符串片段,但所有这些引用都会被丢弃

例如,
parse
中有一个不需要的引用:

fn parse(&self) -> Result<(), &'s str> {
    Err( self.context.0)
    //  ^ no & needed
}
fn解析(&self)->结果{
解析器{context:&context}.parse()
}
另见:

虽然我找不到这个新的省略规则的详细解释


在版本指南中。

感谢Jmb的评论和Shepmaster的一些回答,现在我确实清楚了,我的困惑是关于RAII规则和所有权

也就是说,字符串是在
main
范围内创建的,匿名
Context
实例不是拥有字符串的所有权,它只是借用了一个引用,因此即使在
parse_Context
结尾处连同借用的引用一起删除实例,复制到
Err
对象的引用仍然存在,并指向现有字符串——因此我们使用受约束的生存期变量,编译器能够推断内部字符串引用的生存期

struct Context<'s>(&'s str);
→ 类型为
Parser
的值包含对具有某个生存期
'c
的上下文的引用。此上下文包含一个字符串,其中包含一些其他的生存期

impl<'c, 's> Parser<'c, 's>
{
    fn parse(&self) -> Result<(), &'s str>
    {
        Err(self.context.0)
    }
}
→ 我不确定这是在什么地方指定的,但显然编译器推断返回字符串的生存期与上下文使用的
参数相同。请注意,即使将上下文本身移动到
parse_context
,这也只会影响上下文本身,而不会影响它所包含的字符串

fn main()
{
    let mut s = String::new();
→ 创建一个在
main

    s += "Avail";
    s += "able?";
    if let Err(text) = parse_context(Context(&s))
→ 创建新上下文并将其移动到
parse_context
。它将在
parse\u context
的末尾自动删除。它保存对字符串
s
的引用,该引用在
main
结束之前有效,
parse\u context
返回与
s
具有相同生存期的字符串⇒ <代码>文本在
main
结束前有效

    {
        println!("{}", text);
    }
}

→ 没问题:
text
main

结束之前都是有效的,让我把话说清楚:在identity函数中,
s
(其类型是引用)的副本不是引用本身的副本,而是它引用的整个对象(在本例中是切片)?否,
s
的副本实际上就是参考文件的副本。但是,在您的情况下,它是对
main
函数中定义的
'static
字符串
“Available?”
的引用,由于它是
'static
,因此永远不会被删除。它不再是
'static
,但它仍然是对
main
中定义的字符串的引用,因此它在
main
期间仍然有效。照此,寿命
被推断为“直到函数
main
结束”。@PeterVaro这不是“我的”风格,而是通过RFCs商定并由rustfmt颁布的Rust社区风格。我编辑每一个Rust Q&A,为寻找问题答案的人提供统一的体验,而不想学习任意的海报空白区奇思妙想。SO的目的是快速阅读一个问题,看看它是否相关,以及获得信息的答案。非惯用风格的选择有损于这一目标。@Shepmaster是的,除了标准库和其他官方代码片段都没有遵循我到目前为止发现的完全相同的规则,以及
rustfmt
(感谢上帝)是可配置的,不像
gofmt
prettier
那样愚蠢地攻击。这是对我在回答中总结的相同结论的更详细解释。这正是我要找的。谢谢请始终使用
rustfmt
根据指南格式化代码。您可以在的右上角的“工具”下找到它
    {
        println!("{}", text);
    }
}
    s += "Avail";
    s += "able?";
    if let Err(text) = parse_context(Context(&s))
    {
        println!("{}", text);
    }
}