Skip to content

2.10 认识生命周期 问题 #1457

Open
@W2Q3Q1

Description

@W2Q3Q1

认识生命周期这一章节,对生命周期的部分描述或许有些问题。
文中有如下描述:

但是,话说回来,存在即合理,有时候,'static 确实可以帮助我们解决非常复杂的生命周期问题甚至是无法被手动解决的生命周期问题,那么此时就应该放心大胆的用,只要你确定:你的所有引用的生命周期都是正确的,只是编译器太笨不懂罢了。

然而,RUST中的生命周期和unsafe代码有明显不同,其并不是以放宽安全性要求为代价进行的“优化”,而仅仅是复杂的生命周期推演过程中的一个“中间提示”。换句话说,如果一个函数的参数、返回值标注了'static生命周期,则编译器会检查实际传入的参数和返回值是否满足'static。同理,如果函数参数、返回值标注了'a,编译器会在每个调用处,分别检查输入参数、返回值在调用域内是否满足要求,同时会检查:假设输入参数为'a的情况下,输出'a是否成立。如果上述要求不成立,会报错,而不是假设程序员知道自己在干什么,从而返回不那么安全的代码有一个优化特例,后面说)。
例如,如下代码会报错:

// 不满足:假设输入参数为'a的情况下,输出'a成立
fn TestFunc<'a>(a: &'a TestStruct) -> &mut 'a TestStruct {
    &mut TestStruct {}
}

特例:你可以从函数内返回一个 Copyable的 不可变的 直接创建的 临时对象引用。例如:

struct TestStruct {
    i: i32,
}
fn TestFunc<'a>(a: &'a TestStruct) -> &'a TestStruct {
    &TestStruct { i: 32 }
}

但是这个不行:

// Not Copyable
struct TestStruct {
    a: String,
}
fn TestFunc<'a>(a: &'a TestStruct) -> &TestStruct {
    &TestStruct {
        a: String::from("abc"),
    }
}

这个也不行:

// 可变
struct TestStruct {
    i: i32,
}
fn TestFunc(a: &TestStruct) -> &mut TestStruct {
    &mut TestStruct { i: 32 }
}

这个也不行:

// 有临时变量,非直接创建后返回
struct TestStruct {
    i: i32,
}
fn TestFunc(a: &TestStruct) -> &TestStruct {
    let x = TestStruct { i: 32 };
    x
}

因此,你不能返回一个'a的输入,作为'static的返回值。即使标注了也不行!如下:

struct TestStruct {
    i: i32,
}
fn TestFunc<'a>(input: &'a TestStruct) -> &'static TestStruct {
    input
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions