簡體   English   中英

為什么我可以在 Rust 中的向量末尾開始切片?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM