W3Cschool
恭喜您成為首批注冊用戶
獲得88經(jīng)驗值獎勵
可變性,可以改變東西的能力,與其他語言相比它在 Rust 中有點不同??勺冃缘牡谝粋€方面是它的非默認狀態(tài):
let x = 5;
x = 6; // error!
我們可以應(yīng)用 mut 關(guān)鍵字來介紹可變性:
let mut x = 5;
x = 6; // no problem!
這是一個可變的變量綁定。當一個綁定是可變時,這意味著你可以更改綁定的指向。所以在上面的例子中,不是 x 的值發(fā)生變化,而是這個綁定從 i32 更改為其他。
如果你想要更改綁定的指向,你將需要一個可變的引用:
let mut x = 5;
let y = &mut x;
y 是一個綁定到一個可變引用的不可變值,這意味著你不可以將 y 綁定到其他 ( y = &mut z ),但是你可以改變綁定到 y上的東西 ( *y=5 ).細微的差別。
當然,如果你兩個都需要,可以如下書寫:
let mut x = 5;
let mut y = &mut x;
現(xiàn)在 y 可以綁定到另一個值,并且這個引用的值可以改變。
注意到 mut 是<模式的一部分是非常重要的,你可以這樣編寫代碼:
let (mut x, y) = (5, 6);
fn foo(mut x: i32) {
然而,在 Rust 中當我們說有些東西是‘不變’的,這并不意味著它不可以更改:我們說的是它有‘外部可變性’??紤]如下例子,Arc<T>:
use std::sync::Arc;
let x = Arc::new(5);
let y = x.clone();
當我們調(diào)用 clone() 時,Arc<T> 需要更新引用計數(shù)。然而我們在這里還沒有使用 mut,x 是一個不可變綁定,同時我們沒有使用 &mut 5 或者任何東西。所以誰給?
要理解這一點,我們需要回到 Rust 的指導(dǎo)哲學(xué)的核心,內(nèi)存安全,和 Rust 保證的機制,所有權(quán)系統(tǒng),和更具體的,借用:
You may have one or the other of these two kinds of borrows, but not both at the same time:
one or more references (&T) to a resource.
exactly one mutable reference (&mut T)
所以,這就是‘不變’的真正定義:有兩個指針指向內(nèi)容是否安全?在 Arc<T> 的例子中,是的:變化完全包含在內(nèi)部結(jié)構(gòu)本身中。它不是面向用戶的。為此,將 &T 傳遞給 clone()。但是,如果將 &mut T 傳遞給 clone(),將會成為一個問題:
其它類型,諸如 std::cell 模塊中,具有相反的:內(nèi)部可變性。例如:
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
RefCell 用 borrow_mut() 函數(shù)來將 &mut 引用傳遞到它包含的東西中。那樣不危險嗎?如果那樣做會怎樣:
use std::cell::RefCell;
let x = RefCell::new(42);
let y = x.borrow_mut();
let z = x.borrow_mut();
事實上,這將在運行時引起恐慌。這是 RefCell 做的事情:它在運行時保證 Rust 的借用規(guī)則,同時如果它們違背了規(guī)則時的 panic!。這允許我們能夠繞過 Rust 的不變規(guī)則的另一方面。讓我們先講講吧。
可變性是借用 ( &mut ) 或者綁定 ( let mut ) 的一個屬性。這意味著,例如,你不能有一個結(jié)構(gòu)體既有一些字段可變還有一些不可變:
struct Point {
x: i32,
mut y: i32, // nope
}
一個結(jié)構(gòu)體在綁定方面的可變性:
struct Point {
x: i32,
y: i32,
}
let mut a = Point { x: 5, y: 6 };
a.x = 10;
let b = Point { x: 5, y: 6};
b.x = 10; // error: cannot assign to immutable field `b.x`
然而,通過使用 Cell<T>,你可以模仿字段級可變性:
use std::cell::Cell;
struct Point {
x: i32,
y: Cell<i32>,
}
let point = Point { x: 5, y: Cell::new(6) };
point.y.set(7);
println!("y: {:?}", point.y);
以上代碼將打印 y: Cell { value: 7 }。我們已經(jīng)成功更新 y。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號-3|閩公網(wǎng)安備35020302033924號
違法和不良信息舉報電話:173-0602-2364|舉報郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號
聯(lián)系方式:
更多建議: