字符串字面量
let s = "hello";
變量s
屬于字符串字面量,它們屬于硬編碼進程序的字符串值,屬于不可變的類型。但并不是所有字符串的值都能夠在編寫代碼時確定。
String類型
String
類型會在堆上分配到自己需要的存儲空間,所以它能夠處理在編譯時未知大小的文本。
對于String
類型而言,為了支持一個可變、可增長的文本類型,我們需要在堆上分配一塊在編譯時未知大小的內存來存放數據。這同時也意味著:
- 我們使用的內存是操作系統在運行時動態分配出來的
- 當使用完
String
時,我們需要通過某種方式將這些內存歸還給操作系統
let s: String = String::from("hello");let s2 = s;
String
對象的內存布局實際由3部分組成,如下圖所示:一個指向存放字符串內容的指針(ptr
)、一個長度(len
)及一個容量(capacity
),這部分的數據存儲在棧上。
將變量s
賦值給s2
,其實是棧上將變量的所有權轉移給了s2
。RUST
也不需要在s
離開作用域后做任何清理,試圖在s2
創建完畢后使用s
會導致編譯錯誤。
淺拷貝
假如你在其它語言中接觸過淺拷貝(shallow copy
)和深拷貝(deep copy
)這兩個術語,那么你也許會將這里的復制行為視作淺拷貝。但由于RUST
同時使第一個變量無效了,所以我們使用了新的術語移動(move
)來描述這一行為,而不再使用淺拷貝。
RUST
的設計原則:RUST
永遠不會自動地創建數據的深度拷貝。因此在RUST
中,任何自動的賦值操作都可以被視為高效的。
clone
當你確實需要去深拷貝String
堆上的數據,而不僅僅是棧數據時,就可以使用一個名為clone
的方法。
let s: String = String::from("hello");let s2 = s.clone();
字符串切片
字符串切片是指String
對象中某個連續部分的引用,它的使用方式如下:
let s: String = String::from("hello");let hello = &s[0..5];
我們在一對方括號中指定了切片的范圍區間[start_index..end_index]
,其中的end_index
是切片終止位置的的下一個索引值。
切片數據結構在內部存儲了指向其實位置的引用和一個描述切片長度的字段,這個切片長度就等于end_index-start_index
。