在 Rust 中保留對字串的參考集合的最有效方法是什么?
具體來說,我將以下代碼作為決議命令列引數的一些代碼的開頭(要添加選項決議):
let args: Vec<String> = env::args().collect();
let mut files: Vec<&String> = Vec::new();
let mut i = 1;
while i < args.len() {
let arg = &args[i];
i = 1;
if arg.as_bytes()[0] != b'-' {
files.push(arg);
continue;
}
}
args正如https://doc.rust-lang.org/book/ch12-01-accepting-command-line-arguments.html 中所推薦的,宣告為Vec<String>。據我了解,這意味著構建了新的字串,這有點令人驚訝;我本來希望命令列引數已經存在于記憶體中,并且只需要創建一個對現有字串的參考向量。但編譯器似乎同意它需要是Vec<String>.
對files;做同樣的事情似乎效率低下;肯定沒有必要進一步復制。相反,我已將其宣告為Vec<&String>,據我所知,這意味著僅創建對現有字串的參考向量,這是最佳的。(并不是說它對命令列引數產生了可測量的性能差異,但我現在想弄清楚這一點,以便以后在處理更大的資料時可以得到它。)
當我稍微感到困惑的是,防銹似乎經常推薦 str過String,確實編譯器很高興有files保持或者str或&str。
我現在最好的猜測是str,作為參考字串切片的物件,當您只想保留對字串的一部分的參考時最有效,但是當您知道想要整個字串時,它會更好跳過創建切片物件的開銷,只需保留&String.
以上是正確的,還是我遺漏了什么?
uj5u.com熱心網友回復:
args正如https://doc.rust-lang.org/book/ch12-01-accepting-command-line-arguments.html 中所推薦的,宣告為Vec<String>。據我了解,這意味著構建了新的字串,這有點令人驚訝;我原以為記憶體中已經存在命令列引數
命令列引數確實存在于記憶體中,但
- 他們不是
String,他們甚至不能保證是 UTF8 - 他們不在一個
Vec布局中
從根本上講,它們的存盤甚至沒有任何規定,您只知道它們是 C 字串(以空字符結尾),并且您會得到一個指向這些字串的指標陣列,其最后一個元素是空指標。
這就是為什么args是一個迭代的String:它會懶洋洋地解碼和你要求的話,其實驗證每個引數,你可以檢查它的源代碼:
pub fn args() -> Args {
Args { inner: args_os() }
}
#[stable(feature = "env", since = "1.0.0")]
impl Iterator for Args {
type Item = String;
fn next(&mut self) -> Option<String> {
self.inner.next().map(|s| s.into_string().unwrap())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.inner.size_hint()
}
}
現在我不能告訴你為什么args_osyieldsOsString而不是OsStr,我會假設某種型別的可移植性(例如,某些平臺可能無法保證整個程式的 args 資料存在)。
我現在最好的猜測是 str 作為參考字串切片的物件,當您只想保留對字串的一部分的參考時最有效,但是當您知道想要整個字串時,它是最好跳過創建切片物件的開銷,只保留 &String。
以上是正確的,還是我遺漏了什么?
&String僅出于規律性而存在(從某種意義上說,它是共享參考的自然產物并String同時存在),它實際上并沒有用:&String僅允許您訪問 的只讀/不可變方法String,所有這些方法都真正由str除了capacity()(很少有用)和一些從strto復制的方法String(我假設是為了效率),如len或is_empty。
&str通常也比 更有效&String:雖然它的大小是 2 個字(指標、長度)而不是一個(指標),但它直接指向相關資料而不是指向相關資料的指標(并且需要取消參考才能訪問長度屬性)。因此,&String很少被認為是有用的和大眼夾將警惕它在默認情況下(也&Vec如&[]通常是更好地為同樣的原因)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/388749.html
上一篇:strcat&覆寫
下一篇:根據用戶輸入替換字串C
