简体   繁体   English

常量和静态变量有什么区别,我应该选择哪个?

[英]What is the difference between a constant and a static variable and which should I choose?

I know this from RFC 246 :我从RFC 246知道这一点:

  • constants declare constant values .常量声明常量值 These represent a value, not a memory address.这些代表一个值,而不是内存地址。 This is the most common thing one would reach for and would replace static as we know it today in almost all cases.这是最常见的事情,几乎在所有情况下都会取代我们今天所知道的static
  • statics declare global variables .静态声明全局变量 These represent a memory address.这些代表一个内存地址。 They would be rarely used: the primary use cases are global locks, global atomic counters, and interfacing with legacy C libraries.它们很少使用:主要用例是全局锁、全局原子计数器以及与遗留 C 库的接口。

I don't know what is actually different between the two when I try to maintain a table.当我尝试维护一张桌子时,我不知道两者之间实际上有什么不同。

Which one should I choose?我应该选择哪一个?

Mutability可变性

A const ant in Rust is immutable. Rust 中的const ant 是不可变的。 You neither can reassign nor modify it:您既不能重新分配也不能修改它:

struct Foo(u32);

const FOO: Foo = Foo(5);
const mut FOO: Foo = Foo(5); // illegal

fn main() {
    FOO = Foo(1); //illegal
    FOO.0 = 2; //illegal
}

A static variable can be mutable and therefore can either be modified or reassigned. static变量可以是可变的,因此可以修改或重新分配。 Note that writing/modifying a global static variable is unsafe and therefore needs an unsafe block:请注意,写入/修改全局static变量是不安全的,因此需要一个unsafe块:

struct Foo(u32);
static FOO: Foo = Foo(5);
static mut FOO_MUT: Foo = Foo(3);

fn main() {
    unsafe {
        FOO = Foo(1); //illegal
        FOO.0 = 2; //illegal

        FOO_MUT = Foo(1);
        FOO_MUT.0 = 2;
    }
}

Occurrences发生次数

When you compile a binary, all const "occurrences" (where you use that const in your source code) will be replaced by that value directly.当你编译一个二进制文件时,所有的const “出现”(你在源代码中使用该const地方)将直接被该值替换。

static s will have a dedicated section in your binary where they will be placed (the BSS section , see Where are static variables stored in C and C++? for further information). static将在您的二进制文件中有一个专门的部分,它们将被放置在其中( BSS 部分,请参阅C 和 C++ 中静态变量存储在哪里?了解更多信息)。


All in all, stick to a const whenever possible.总而言之,尽可能坚持使用const When not possible, because you need to initialize a variable later in the program of with non- const methods, use lazy_static!如果不可能,因为您需要在使用非const方法的程序中稍后初始化变量,请使用lazy_static! . .

Interior mutability内部可变性

While both const and static can use interior mutability you should never ever do it with a const.虽然conststatic都可以使用内部可变性,但您永远不应该使用 const 来这样做。 Here's an example这是一个例子

use std::sync::atomic::{AtomicU32, Ordering};

static STATIC: AtomicU32 = AtomicU32::new(0);
const CONST: AtomicU32 = AtomicU32::new(0);

fn print() {
    println!("static: {}", STATIC.load(Ordering::Relaxed));
    println!("const:  {}", CONST.load(Ordering::Relaxed));
}

fn main() {
    STATIC.store(3, Ordering::Relaxed);
    CONST.store(3, Ordering::Relaxed);

    print();
}

This compiles fine without any warnings, but leads to unwanted behavoir.这在没有任何警告的情况下编译得很好,但会导致不必要的行为。 Output:输出:

static: 3
const:  0

When using clippy, it will show the two following warnings:使用clippy时,会显示以下两个警告:

warning: a `const` item should never be interior mutable
 --> src/main.rs:4:1
  |
4 | const CONST: AtomicU32 = AtomicU32::new(0);
  | -----^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  | |
  | make this a static item (maybe with lazy_static)
  |
  = note: `#[warn(clippy::declare_interior_mutable_const)]` on by default
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#declare_interior_mutable_const

warning: a `const` item with interior mutability should not be borrowed
 --> src/main.rs:8:27
  |
8 |     println!("const: {}", CONST.load(Ordering::Relaxed));
  |                           ^^^^^
  |
  = note: `#[warn(clippy::borrow_interior_mutable_const)]` on by default
  = help: assign this const to a local or static variable, and use the variable here
  = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const

warning: a `const` item with interior mutability should not be borrowed
  --> src/main.rs:13:5
   |
13 |     CONST.store(3, Ordering::Relaxed);
   |     ^^^^^
   |
   = help: assign this const to a local or static variable, and use the variable here
   = help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#borrow_interior_mutable_const

There's not much practical difference if your variable isn't intended to change.如果您的变量不打算更改,则没有太大的实际区别。

Constants are inlined at compilation, which means they're copied to every location they're used, and thus are usually more efficient, while statics refer to a unique location in memory and are more like global variables.常量在编译时内联,这意味着它们被复制到它们使用的每个位置,因此通常更有效,而静态引用内存中的唯一位置,更像是全局变量。

Constants are... constant while statics, while still global, can be mutable.常量是......常量而静态,虽然仍然是全局的,但可以是可变的。

Rust static vs const Rust static vs const

const : const

  • Have no fixed address in memory内存中没有固定地址
  • They're inlined to each place which uses them, this means they are put directly into the binary on the places which use them.它们被内联到每个使用它们的地方,这意味着它们被直接放入使用它们的地方的二进制文件中。
  • Usually faster runtime but bigger executable file because it doesn't have to look up an address like static通常运行速度更快,但可执行文件更大,因为它不必像static一样查找地址

static : static

  • Have a fixed address in memory在内存中有一个固定地址
  • Their value is loaded from this fixed address each place which uses them.它们的值从每个使用它们的固定地址加载。
  • Usually slower runtime because we need to perform the extra instruction of loading the data from the fixed address.通常运行时间较慢,因为我们需要执行从固定地址加载数据的额外指令。 However this could result in a smaller executable file (only when it is used frequently) because it doesn't have to have multiple copies of the value baked into the executable.然而,这可能导致较小的可执行文件(仅当它被频繁使用时),因为它不必将值的多个副本烘焙到可执行文件中。

Example:例子:

    static CDF: i32 = 100;
    const ABC: i32 = 50;

    fn main() {
        println!("{}", CDF); // compiler will put in a load instruction here for the static address
        println!("{}", ABC); // compiler will put the value 50 here directly
    
        // statics can be mutable
        static mut HI: &str = "hi";
    
        // however using mut static is unsafe
        unsafe {
            HI = "HITHERE";
        }
    
        unsafe {
            println!("{}", HI);
        }
    }

The main purpose of static is to allow functions to control an internal value that is remembered across calls, but not be accessible by the main application code. static的主要目的是允许函数控制在调用时记住的内部值,但不能被主应用程序代码访问。 It is similar to Class variables as opposed to Instance variables in other languages.它类似于类变量,而不是其他语言中的实例变量。 Also C and PHP and many other languages have this concept. C 和 PHP 以及许多其他语言也有这个概念。

Example: you want to track how many times a function is called and have a way of resetting the internal counter:示例:您想跟踪函数被调用的次数并有一种重置内部计数器的方法:

fn counter(reset: bool) -> i32 {
    static mut Count: i32 = 0;

    unsafe {
        if reset {
            Count = 0;
        }    
        Count += 1;
        return Count;
    }
}

println!("{}",counter(true));
println!("{}",counter(false));
println!("{}",counter(false));
//println!("{}", Count); // Illegal

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM