Suche…


Syntax

  • const IDENTIFIER: type = constexpr;
  • statisch [mut] IDENTIFIER: type = expr;
  • lazy_static! {statischer Ref IDENTIFIER: Typ = Ausdruck; }

Bemerkungen

  • const Werte sind immer inline und haben keine Adresse im Speicher.
  • static Werte werden nie eingebettet und haben eine Instanz mit einer festen Adresse.
  • static mut Werte sind nicht speichersicher und können daher nur in einem unsafe Block abgerufen werden.
  • Die Verwendung globaler statischer variabler Variablen in Multithread-Code kann manchmal gefährlich sein. Daher sollten Sie std :: sync :: Mutex oder andere Alternativen in Betracht ziehen
  • lazy_static Objekte sind unveränderlich, werden nur einmal initialisiert, werden von allen Threads gemeinsam verwendet und können direkt aufgerufen werden (es sind keine Wrapper-Typen beteiligt). Im Gegensatz dazu sind thread_local Objekte veränderbar, werden für jeden Thread einmalig initialisiert und Zugriffe sind indirekt (einschließlich des Wrapper-Typs LocalKey<T> ).

Const

Das Schlüsselwort const deklariert eine globale konstante Bindung.

const DEADBEEF: u64 = 0xDEADBEEF;

fn main() {
    println("{:X}", DEADBEEF);
}

Dies gibt aus

DEADBEEF

Statisch

Das static Schlüsselwort deklariert eine globale statische Bindung, die möglicherweise veränderbar ist.

static HELLO_WORLD: &'static str = "Hello, world!";

fn main() {
    println("{}", HELLO_WORLD);
}

Dies gibt aus

Hello, world!

lazy_static!

Verwenden Sie die Kiste lazy_static , um globale unveränderliche Variablen zu erstellen, die zur Laufzeit initialisiert werden. Wir verwenden HashMap als Demonstration.

In Cargo.toml :

[dependencies]
lazy_static = "0.1.*"

In main.rs :

#[macro_use]
extern crate lazy_static;

lazy_static! {
    static ref HASHMAP: HashMap<u32, &'static str> = {
        let mut m = HashMap::new();
        m.insert(0, "hello");
        m.insert(1, ",");
        m.insert(2, " ");
        m.insert(3, "world");
        m
    };
    static ref COUNT: usize = HASHMAP.len();
}

fn main() {
    // We dereference COUNT because it's type is &usize
    println!("The map has {} entries.", *COUNT);

    // Here we don't dereference with * because of Deref coercions
    println!("The entry for `0` is \"{}\".", HASHMAP.get(&0).unwrap());
}

Thread-lokale Objekte

Ein Thread-lokales Objekt wird bei seiner ersten Verwendung in einem Thread initialisiert. Und wie der Name schon sagt, erhält jeder Thread unabhängig von anderen Threads eine frische Kopie.

use std::cell::RefCell;
use std::thread;

thread_local! {
    static FOO: RefCell<f32> = RefCell::new(1.0);
}

// When this macro expands, `FOO` gets type `thread::LocalKey<RefCell<f32>>`.
//
// Side note: One of its private member is a pointer to a function which is
// responsible for returning the thread-local object. Having all its members
// `Sync` [0], `LocalKey` is also implicitly `Sync`.
//
// [0]: As of writing this, `LocalKey` just has 2 function-pointers as members

fn main() {
    FOO.with(|foo| {
        // `foo` is of type `&RefCell<f64>`
        *foo.borrow_mut() = 3.0;
    });

    thread::spawn(move|| {
        // Note that static objects do not move (`FOO` is the same everywhere),
        // but the `foo` you get inside the closure will of course be different.
        FOO.with(|foo| {
            println!("inner: {}", *foo.borrow());
        });
    }).join().unwrap();

    FOO.with(|foo| {
        println!("main: {}", *foo.borrow());
    });
}

Ausgänge:

inner: 1
main: 3

Sicher statisch mut mit mut_static

Veränderliche globale Elemente ( static mut , die den inhärenten Widerspruch ihrer Verwendung hervorheben) sind nicht sicher, da der Compiler nur schwer eine korrekte Verwendung sicherstellen kann.

Die Einführung von sich gegenseitig ausschließenden Sperren um Daten ermöglicht jedoch speichersichere, veränderliche Globals. Dies bedeutet jedoch NICHT, dass sie logisch sicher sind!

#[macro_use]
extern crate lazy_static;
extern crate mut_static;

use mut_static::MutStatic;

pub struct MyStruct { value: usize }

impl MyStruct {
    pub fn new(v: usize) -> Self{
        MyStruct { value: v }
    }
    pub fn getvalue(&self) -> usize { self.value }
    pub fn setvalue(&mut self, v: usize) { self.value = v }
}

lazy_static! {
    static ref MY_GLOBAL_STATE: MutStatic<MyStruct> = MutStatic::new();
}

fn main() {
    // Here, I call .set on the MutStatic to put data inside it.
    // This can fail.
    MY_GLOBAL_STATE.set(MyStruct::new(0)).unwrap();
    {
        // Using the global state immutably is easy...
        println!("Before mut: {}", 
                 MY_GLOBAL_STATE.read().unwrap().getvalue());
    }
    {
         // Using it mutably is too...
         let mut mut_handle = MY_GLOBAL_STATE.write().unwrap();
         mut_handle.setvalue(3);
         println!("Changed value to 3.");
    } 
    {
        // As long as there's a scope change we can get the 
        // immutable version again...
        println!("After mut: {}", 
                 MY_GLOBAL_STATE.read().unwrap().getvalue());
    }
    {
        // But beware! Anything can change global state!
        foo();
        println!("After foo: {}", 
                 MY_GLOBAL_STATE.read().unwrap().getvalue());
    }
 
}

// Note that foo takes no parameters
fn foo() {
    let val;
    {
        val = MY_GLOBAL_STATE.read().unwrap().getvalue();
    }
    {
        let mut mut_handle = 
            MY_GLOBAL_STATE.write().unwrap();
        mut_handle.setvalue(val + 1);
    }
}

Dieser Code erzeugt die Ausgabe:

Before mut: 0
Changed value to 3.
After mut: 3
After foo: 4

Dies sollte in Rust normalerweise nicht passieren. foo() nahm keinen veränderlichen Verweis auf irgendetwas an, also hätte es nichts mutieren sollen, und doch tat es dies. Dies kann zu sehr schwer zu debugierenden Logikfehlern führen.

Andererseits ist dies manchmal genau das, was Sie wollen. Zum Beispiel erfordern viele Game-Engines einen globalen Cache mit Bildern und anderen Ressourcen, der nur langsam geladen wird (oder eine andere komplexe Ladestrategie verwendet) - MutStatic eignet sich für diesen Zweck.



Modified text is an extract of the original Stack Overflow Documentation
Lizenziert unter CC BY-SA 3.0
Nicht angeschlossen an Stack Overflow