'& self'和'&'a self'有什么区别? [英] What is the difference between '&self' and '&'a self'?

查看:89
本文介绍了'& self'和'&'a self'有什么区别?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近遇到了一个错误,只需通过更改即可解决

I recently had an error which was simply resolved by changing

impl<'a> Foo<'a> {
    fn foo(&'a self, path: &str) -> Boo<'a> { /* */ }
}

impl<'a> Foo<'a> {
    fn foo(&self, path: &str) -> Boo { /* */ }
}

根据我的理解,这没有任何意义,因为我认为第二个版本与应用了生命周期省略的第一个完全相同.

which did not make sense according to my understanding, as I thought that the second version is exactly the same as the first with applied lifetime elision.

如果我们为该方法引入了新的生命周期,则根据 nomicon .

In case we introduce a new lifetime for the method this seems to be the case according this example from the nomicon.

fn get_mut(&mut self) -> &mut T;                        // elided
fn get_mut<'a>(&'a mut self) -> &'a mut T;              // expanded

那么这段代码和我的第一个代码片段之间有什么区别.

So what are the differences between this and my first code snipped.

推荐答案

fn foo(&'a self, ...) ...中的生存期'a是为impl<'a>定义的,也就是说,所有foo调用都相同.

Lifetime 'a in fn foo(&'a self, ...) ... is defined for impl<'a>, that is it is the same for all foo calls.

寿命'a.不同的get_mut调用可以具有不同的'a值.

Lifetime 'a in fn get_mut<'a>(&'a mut self) ... is defined for the function. Different calls of get_mut can have different values for 'a.

您的代码

impl<'a> Foo<'a> {
    fn foo(&'a self, path: &str) -> Boo<'a> { /* */ }
}

不是延长寿命.该代码将借用&'a self的生存期与结构Foo<'a>的生存期联系起来.如果Foo<'a>'a上不变,那么只要'aself应该保持借用.

is not the expansion of elided lifetime. This code ties lifetime of borrow &'a self to the lifetime of structure Foo<'a>. If Foo<'a> is invariant over 'a, then self should remain borrowed as long as 'a.

消除寿命的正确扩展是

impl<'a> Foo<'a> {
    fn foo<'b>(&'b self, path: &str) -> Boo<'b> { /* */ }
}

此代码不依赖于结构Foo的变化而能够借用self来缩短生命周期.

This code doesn't depend on variance of structure Foo to be able to borrow self for shorter lifetimes.

变异结构和不变结构之间差异的例子.

Example of differences between variant and invariant structures.

use std::cell::Cell;

struct Variant<'a>(&'a u32);

struct Invariant<'a>(Cell<&'a u32>);

impl<'a> Variant<'a> {
    fn foo(&'a self) -> &'a u32 {
        self.0
    }
}

impl<'a> Invariant<'a> {
    fn foo(&'a self) -> &'a u32 {
        self.0.get()
    }
}

fn main() {
    let val = 0;
    let mut variant = Variant(&val);// variant: Variant<'long>
    let mut invariant = Invariant(Cell::new(&val));// invariant: Invariant<'long>
    {
        let r = variant.foo();
        // Pseudocode to explain what happens here
        // let r: &'short u32 = Variant::<'short>::foo(&'short variant);
        // Borrow of `variant` ends here, as it was borrowed for `'short` lifetime

        // Compiler can do this conversion, because `Variant<'long>` is
        // subtype of Variant<'short> and `&T` is variant over `T`
        // thus `variant` of type `Variant<'long>` can be passed into the function 
        // Variant::<'short>::foo(&'short Variant<'short>)
    }
    // variant is not borrowed here
    variant = Variant(&val);

    {
        let r = invariant.foo();
        // compiler can't shorten lifetime of `Invariant`
        // thus `invariant` is borrowed for `'long` lifetime
    }
    // Error. invariant is still borrowed here
    //invariant = Invariant(Cell::new(&val));
}

游乐场链接

这篇关于'&amp; self'和'&amp;'a self'有什么区别?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆