[英]Why can I start a slice past the end of a vector in Rust?
給定v = vec,[1,2,3,4]
,為什么v[4..]
返回一個空向量,但是v[5..]
恐慌,而v[4]
和v[5]
都恐慌? 我懷疑這與切片的實現有關,但沒有指定起點或終點,但我在網上找不到任何信息。
這僅僅是因為std::ops::RangeFrom
被定義為“包含在以下范圍內”。
快速回顧所有管道: v[4..]
使用4..
(解析為std::ops::RangeFrom
)作為參數對std::ops::Index
脫糖。 std::ops::RangeFrom
實現std::slice::SliceIndex
並且Vec
對任何實現std::slice::SliceIndex
的參數都有一個std::ops::Index
實現。 所以你正在看的是一個RangeFrom
被用於std::ops::Index
Vec
。
std::ops::RangeFrom
定義為始終包含下限。 例如[0..]
將包括被索引的事物的第一個元素。 如果(在您的情況下) Vec
為空,則[0..]
將是空切片。 注意:如果下限不包含在內,則根本無法在不引起恐慌的情況下對空的Vec
進行切片,這會很麻煩。
一種簡單的思考方式是“放置圍欄的位置”。
vec,[0, 1, 2 ,3]
中的v[0..]
] 是
| 0 1 2 3 |
^
|- You are slicing from here. This includes the
entire `Vec` (even if it was empty)
在v[4..]
中是
| 0 1 2 3 |
^
|- You are slicing from here to the end of the Vector.
Which results in, well, nothing.
而v[5..]
將是
| 0 1 2 3 |
^
|- Slicing from here to infinity is definitely
outside the `Vec` and, also, the
caller's fault, so panic!
v[3..]
是
| 0 1 2 3 |
^
|- slicing from here to the end results in `&[3]`
雖然另一個答案解釋了如何理解和記住 Rust 標准庫中實現的索引行為,但它的真正原因與技術限制無關。 它歸結為 Rust 標准庫的作者做出的設計決定。
給定
v = vec,[1,2,3,4]
,為什么v[4..]
返回一個空向量,但v[5..]
恐慌 [..]?
因為是這樣決定的。 如果起始索引大於切片的長度,下面處理切片索引( 完整源代碼)的代碼將出現恐慌。
fn index(self, slice: &[T]) -> &[T] {
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*self.get_unchecked(slice) }
}
fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
panic!("range start index {} out of range for slice of length {}", index, len);
}
如何以不同的方式實施? 我個人喜歡 Python 的做法。
v = [1, 2, 3, 4]
a = v[4] # -> Raises an exception - Similar to Rust's behavior (panic)
b = v[5] # -> Same, raises an exception - Also similar to Rust's
# (Equivalent to Rust's v[4..])
w = v[4:] # -> Returns an empty list - Similar to Rust's
x = v[5:] # -> Also returns an empty list - Different from Rust's, which panics
Python 的方法不一定比 Rust 的方法好,因為總會有取舍。 Python 的方法更方便(不需要檢查起始索引是否不大於長度),但如果有錯誤,則更難找到,因為它不會提前失敗。
盡管 Rust 在技術上可以遵循 Python 的方法,但它的設計者決定提前失敗,以便更快地找到錯誤,但代價是一些不便(程序員需要確保開始索引不大於長度) .
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.