1. 程式人生 > >Rust 未繫結可變引用 和繫結可變引用的區別

Rust 未繫結可變引用 和繫結可變引用的區別

Rust 繫結可變引用 和可變繫結的區別

在Rust Documents Api 中 我們經常會看到如下的寫法

	//繫結可變引用
	let f = &mut String::from("what something");
	//可變繫結
	let mut f = String::from("what something");

這兩種語法的區別是很大的。比如在如下程式碼中:

fn main(){
	let mut j;
	{
		let f = &mut String::from("what something");
		j = f;
		// string "what something" died in the scope
	}
	j.push('.');
	print!("{}\n",j);
}
fn main(){
	let mut j;
	{
		let f = String::from("what something");
		j = f;
	}
	j.push('.');
	print!("{}\n",j);
}

第一種寫法會編譯報錯。而第二種寫法則可以正常執行。其原因是Rust的所有權規則: 在Rust中 所有值(分配在堆上或者分配在棧上的記憶體)有且只有一個稱之為所有者的變數(繫結)。 值有且只有一個所有者。當所有者離開作用域時,這個值(記憶體)將被丟棄。

在第一種寫法中,"String::from("what something")並沒有一個所有者變數。這叫做一個temporary value

臨時值(記憶體),其作用域為當前作用域。且其任何的不可變引用或可變借用在其離開作用域之後都會無效。 因此, j = f在遇到第一個}時無效。此時j指向的值被丟棄。編譯器會報錯。

在第二種寫法中,f 是String::from("what something")的擁有者,當呼叫j = fString::from("what something")被移動到了 j變數中,因此在第一個}之後記憶體並被沒有被回收。所以第二種寫法可以編譯通過。

結論

當在函式呼叫時,我們需要一些臨時變數來當作引數值,並確定之後不會使用,則可以使用&mut String::("what something") 這在某些時候是很有用的。 然而,如果我們不想rustc釋放掉某塊記憶體,我們必須指定一個記憶體的所有者,並通過移動語義確保其所有者有效。