首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >为什么我可以返回对函数的自有值的引用?

为什么我可以返回对函数的自有值的引用?
EN

Stack Overflow用户
提问于 2019-04-23 23:00:21
回答 3查看 222关注 0票数 1

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

虽然我无法找到这个新的省略规则的详细解释,但我猜想它不仅仅是一个更长、更显式约束:<'c, 's: 'c>的隐式版本。然而,我认为我的困惑可能不是关于这个新的省略规则,但当然,我可能是错的。

我的理解是,parse_context拥有context的所有权,因为它不是借来的,而是实际转移到函数中的。这本身就意味着,context的生存期应该与它所拥有的函数的生存期相匹配,而不管我们在ContextParser中定义的生存期和约束。

基于这些定义,context超过临时Parser的部分对我来说是非常有意义的(毕竟,我们定义了更长的生命周期),但是当contextparse_context的末尾超出范围时,&str引用不会被删除,而我仍然可以安全地返回它--这让我感到困惑。

我错过了什么?编译器如何解释返回的&str的生存期

更新的示例

代码语言:javascript
复制
struct Context<'s>(&'s str);

struct Parser<'c, 's>
{
    context: &'c Context<'s>,
}

impl<'c, 's> Parser<'c, 's>
{
    fn parse(&self) -> Result<(), &'s str>
    {
        Err(self.context.0)
    }
}

fn parse_context(context: Context) -> Result<(), &str>
{
    Parser { context: &context }.parse()
}

fn main()
{
    let mut s = String::new();
    s += "Avail";
    s += "able?";
    if let Err(text) = parse_context(Context(&s))
    {
        println!("{}", text);
    }
}
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-04-24 09:19:19

代码语言:javascript
复制
struct Context<'s>(&'s str);

Context类型的→值持有一个具有某些生存期's的字符串。此生存期至少与上下文的生存期一样长,但可能更长。

代码语言:javascript
复制
struct Parser<'c, 's>
{
    context: &'c Context<'s>,
}

Parser类型的→值持有对具有某些生存期'c的上下文的引用。此上下文与其他生命周期's一起保存一个字符串。

代码语言:javascript
复制
impl<'c, 's> Parser<'c, 's>
{
    fn parse(&self) -> Result<(), &'s str>
    {
        Err(self.context.0)
    }
}

parse函数返回一个具有生存期's的值,即。具有与上下文中存储的字符串相同的生存期,这与上下文本身的生存期不同。

代码语言:javascript
复制
fn parse_context(context: Context) -> Result<(), &str>
{
    Parser { context: &context }.parse()
}

我不确定这是在哪里指定的,但显然编译器推断返回的字符串的生存期与用于上下文的's参数相同。注意,尽管上下文本身被移动到parse_context中,但这只会影响上下文本身,而不会影响它包含的字符串。

代码语言:javascript
复制
fn main()
{
    let mut s = String::new();

main结束时,→创建一个有效的新字符串

代码语言:javascript
复制
    s += "Avail";
    s += "able?";
    if let Err(text) = parse_context(Context(&s))

parse_context创建一个新的上下文并将其移动到→中。它将自动删除在parse_context的末尾。它保存对字符串s的引用,该引用在main结束之前有效,parse_context返回一个与stext有效的字符串相同的字符串,直到main结束为止。

代码语言:javascript
复制
    {
        println!("{}", text);
    }
}

无问题:textmain结束前有效。

票数 1
EN

Stack Overflow用户

发布于 2019-04-24 00:22:45

您是,而不是,它返回函数所拥有值的引用。您正在返回传入的引用的副本。

您的函数是身份函数的详细版本:

代码语言:javascript
复制
fn parse_context(s: &str) -> &str {
    s
}

在实际代码中,您将引用包含字符串切片的结构,然后再引用字符串切片,但所有这些引用都会被丢弃。

例如,在parse中有一个不必要的引用

代码语言:javascript
复制
fn parse(&self) -> Result<(), &'s str> {
    Err( self.context.0)
    //  ^ no & needed
}

此外,如果您启用了一些更多的lints,您将不得不为您的函数签名添加更多的生命周期,这可能会使事情变得更清楚:

代码语言:javascript
复制
#![deny(rust_2018_idioms)]

fn parse_context(context: Context<'_>) -> Result<(), &'_ str> {
    Parser { context: &context }.parse()
}

另请参阅:

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

版本指南中的结构中的推理

票数 2
EN

Stack Overflow用户

发布于 2019-04-24 09:10:19

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

也就是说,该字符串是在main范围中创建的,匿名Context实例是而不是,它只是借用一个引用,因此即使在parse_context结束时,复制到Err对象的引用仍然存在并指向现有字符串--因此我们使用受约束的生存期变量,编译器能够对内部字符串引用的生存期进行推理。

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/55820491

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档