为什么对const进行静态引用会返回对临时变量的引用?

Zac*_*rns 2 lifetime rust borrow-checker

在Rust中,我有以下代码:

pub trait Test: Sized {
    const CONST: Self;
    fn static_ref() -> &'static Self {
        &Self::CONST
    }
}
Run Code Online (Sandbox Code Playgroud)

我的期望是,既然const'static,那么我应该能够引用也是'static。但是,编译器给出以下错误:

pub trait Test: Sized {
    const CONST: Self;
    fn static_ref() -> &'static Self {
        &Self::CONST
    }
}
Run Code Online (Sandbox Code Playgroud)

这里如何引入临时变量?

此外,似乎在某些情况下引用常量确实有效。这是一个简短的具体示例,其中Test的实现略有不同

pub trait Test: Sized {
    fn static_ref() -> &'static Self;
}

struct X;

impl Test for X {
    fn static_ref() -> &'static Self {
        &X
    }
}
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 7

恒定在锈病是编译时间常数,而不是与一个存储器位置的实际变量。Rust编译器可以在任何使用常量的地方替换其实际。如果使用这样一个值的地址,则将获得一个临时地址。

Rust还具有静态变量的概念。这些变量实际上具有在整个程序持续时间内一致的内存位置,并且引用静态变量的确会导致具有'static寿命的引用。

也可以看看:


Pet*_*all 5

conststatic是不同的东西,但经常相互混淆。

static绑定在程序运行期间保存驻留在永久内存位置的数据。这就是为什么您可以从函数返回对它们的引用;他们永远活着,所以你可以给他们'static一生。

const绑定的值不会改变,并且可以在编译时和运行时进行推理。const编译器将内联用于定义使用它的任何地方的表达式。同一常量的两次使用很可能会将其存储在不同的内存地址中,甚至可能重新应用用于构造它的计算。

考虑一个稍微复杂的例子:

struct MyStruct;

impl MyStruct {
    const fn new() -> Self {
        MyStruct
    }
}

impl Test for MyStruct {
    const CONST: Self = MyStruct::new();
}
Run Code Online (Sandbox Code Playgroud)

这是行不通的,因为由于常量是内联的,所以 的实现static_ref现在看起来像这样:

fn static_ref() -> &'static Self {
    &MyStruct::new()
}
Run Code Online (Sandbox Code Playgroud)

它在函数内部创建一个值并尝试返回它。该值不是静态的,因此'static生存期无效。


然而,通过一些重新调整,你可以让一些东西发挥作用:

pub trait Test: Sized + 'static {
    // This is now a reference instead of a value:
    const CONST: &'static Self;

    fn static_ref() -> &'static Self {
        Self::CONST
    }
}

struct MyStruct;

impl MyStruct {
    const fn new() -> Self {
        MyStruct
    }
}

impl Test for MyStruct {
    const CONST: &'static Self = &MyStruct::new();
}
Run Code Online (Sandbox Code Playgroud)

这是有效的,因为CONST它已经是一个'static引用,所以函数可以返回它。所有可能的实现都必须能够获得'static对实现该特征的引用Self,因此不再存在引用临时值的问题。