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