我一直想知道std::string
的substr(pos, len)
方法現在有一段時間的設計背後的基本原理。它對我仍然沒有意義,所以我決定詢問專家。如果pos
參數超過字符串長度加1,該函數會拋出std::out_of_range
異常。這可能有時不方便(甚至令人討厭),但我真正關心的是一致性和最少驚喜的原則。事實證明子字符串的「結束」位置pos+len
被允許超過字符串長度加1。在開始時禁止這種做法,但並不是爲了最終的結果,這讓我感到不一致。允許它到底要我在解釋爲什麼std :: string :: substr會拋出異常而不是返回空字符串?
回報暗示位置的所有字符pos <= i < pos+len
但是,那麼我希望函數返回一個空字符串超過字符串長度的pos
值,而不是拋出異常。作爲一個方面說明,根據這種解釋,如果允許負值pos
(假設它具有簽名類型),則更爲明智。
這給我留下了以下問題:
- 這是否設計出現合乎邏輯的嗎?明智?你有解決不一致問題的令人滿意的方法嗎? 我能想出的唯一可能的解釋是與以空字符結尾的字符串兼容。有了空終止,如果指定的長度超過了結尾,則無關緊要,而超出空字符的開始是內存錯誤。然而,
std::string
是而不是以空終止,而是跟蹤字符串的長度。如果這是真正的原因,那麼我個人會說這是一個非常糟糕的。 - 在性能方面有優勢嗎?我真的會感到驚訝。
- 我是否忽略了可用性方面的優勢?也許一個標準的習慣用法或用例與其他函數一起使用,比如find?在這裏我的印象是返回一個空字符串有可能簡化一些代碼。
- 以後有什麼方法可以改變
substr
的行爲嗎?我猜不是的,因爲默默地破壞現有的代碼必須比生活在這種扭曲中更糟糕......?
它可以很容易地說「從pos'到末尾的子串」,這不是一種不常見的操作。將第二個參數想象爲返回子字符串中字符數的上限。 –
這個問題可能太基於觀點了。您將呈現一個有趣的字符串視圖,就像無限大的虛擬字符緩衝區,您可以從中選擇一個切片,即使在物理範圍之外。不過,我認爲,更細微的錯誤不會被發現。通過拋出一個範圍異常,你至少可以捕捉一些計算得很差的位置值。也許這是原因? – Galik
我一直都這樣說,在合同違約(這裏的前提條件)上拋出異常是糟糕的設計,即使異常是您合同的一部分。調用者會做什麼,捕獲異常並用'pos/= 2'循環調用函數,直到它停止投擲爲止?更好地斷言 - 失敗並提供有用的信息(例如:「消毒您的輸入!」)。但是,STL是很多年前寫的,也許當時人們並不知道更好。現在,我們必須忍受這種行爲。 – KABoissonneault