標題相對自我解釋。我認識到與其他答案的相似之處,但所有這些人都有不同的操作員安排(因此也有不同的施法規則)。所以我需要一個解釋這個特殊情況的答案。是std :: string :: npos == -1總是正確的?
如果有人能指出解釋這個標準的部分,我會很樂意投票並接受答案。
標題相對自我解釋。我認識到與其他答案的相似之處,但所有這些人都有不同的操作員安排(因此也有不同的施法規則)。所以我需要一個解釋這個特殊情況的答案。是std :: string :: npos == -1總是正確的?
如果有人能指出解釋這個標準的部分,我會很樂意投票並接受答案。
否,它並不總是如此。然而,這是一個比較複雜一點比它乍看起來:
在開始的時候,讓我們看到了什麼std::string
是(21.3/1):
頭
<string>
定義basic_string
類模板操縱變長序列焦炭狀物體的 和四個類型定義,string
,u16string
,u32string
,和wstring
,該名稱的特basic_string<char>
,basic_string<char16_t>
,basic_string<char32_t>
,和basic_string<wchar_t>
,respectiv伊利。
開始了以21.4/5:
template<class charT, class traits = char_traits<charT>, class Allocator = allocator<charT> > class basic_string { typedef typename allocator_traits<Allocator>::size_type size_type; static const size_type npos = -1; // [other members omitted] };
注意的是,雖然npos
與-1
初始化,它的類型取決於Allocator::size_type
,這意味着,如果沒有進一步的知識,我們不能簡單地假設那string::npos == -1
甚至會編譯。
現在,string
使用默認分配器(模板參數在標準庫後所提供的所有類型定義默認值),讓我們檢查20.6.9:
typedef size_t size_type;
現在,我們可以基本上將這個問題重寫爲:size_t(-1) == -1
。現在發生什麼取決於子表達式的類型:左手邊顯然有size_t
類型,而右手邊是整數字面值,類型爲int
,這樣寫(沒有進一步限定符)。
結果是true
如果size_t
是至少一樣大int
(對標準的狂熱分子:具有如4.13所定義的較大的整數轉換秩)。否則,左手邊將得到提升到int
,導致像0xFFFF == -1
一個對比(對於size_t
是uint16_t
和int
具有32位),這是false
。
請注意,雖然16位系統本身不再是非常普遍的(除了一些殘餘物的外形非常小),int
並不侷限於標準的32位。目標x86_64與64
位size_t
和128位int
的編譯器將在技術上符合。
所有引用來自C++ 11標準(ISO/IEC 14882:2011)。
沒有爲你從字面上問問題的漏洞。
如果int
有(嚴格)更大的整數轉換等級上低於string::size_type
和int
可以存儲全系列string::size_type
值,然後string::npos == -1
將是錯誤的,因爲這兩個參數會得到晉升爲int
,而不是被晉升爲string::size_type
。
發生這種情況的環境相當不尋常。
這個來自通常的算術轉換:
...
否則,如果具有無符號整數類型操作數的秩大於或等於類型的 排名另一個操作數的帶符號整數類型的操作數應轉換爲 帶無符號整數類型的操作數的類型
否則,如果操作數的類型帶有符號整數類型的rand可以表示所有具有無符號整數類型的操作數的類型的值 ,具有無符號整數類型的操作數應將 轉換爲具有有符號整數類型的操作數的類型。
否則,兩個操作數都應轉換爲無符號整數類型,對應於有符號整數類型的操作數的 類型。
那麼你是否暗示'string :: size_type'不會在符號擴展中轉換爲'int'? – randomusername
@randomusername:'string :: size_type'是無符號的,所以沒有符號位可以擴展;該轉換保留了該值,因此它將轉換爲非負「int」。請注意,'npos'是一個正值:實際上,它是可存儲在'string :: size_type'中的最大值。 – Hurkyl
作爲後續問題,首先將左側的類型轉換爲帶符號的類型會導致表達式得到保證?例如:'(signed size_t)std :: string :: npos == -1' – randomusername
@randomusername該轉換導致未定義的行爲,因爲'npos'的值很大。只需執行以下操作:'std :: string :: npos == std :: string :: size_type(-1)',你很好。 –