[英]string[length()] in C++, is it OK?
我同事的代碼看起來像這樣:
void copy(std::string const& s, char *d) {
for(int i = 0; i <= s.size(); i++, d++)
*d = s[i];
}
他的應用程序崩潰,我認為這是因為這個訪問s
超出范圍,因為條件應該只到s.size() - 1
。
但是我旁邊的其他人說過去有人討論這是合法的。 有人可以幫我清楚一下嗎?
讓我們拋開*d
無效的可能性,因為這與問題所針對的內容無關:當訪問索引std::string::size()
的“元素”時, std::string operator[]()
是否具有良好定義的行為std::string::size()
。
C ++ 03標准具有string::operator[]()
的以下描述(21.3.4“ basic_string
element access”):
const_reference operator[](size_type pos) const; reference operator[](size_type pos);
返回:如果
pos < size()
,則返回data()[pos]
。 否則,如果pos == size()
,則const版本返回charT()
。 否則,行為未定義。
由於示例代碼中的s
是const
,因此行為定義良好, s[s.size()]
將返回空字符。 但是,如果s
不是const string
,則行為將是未定義的。
C ++ 11補救了const
版本的奇數行為,其行為與此邊緣情況下的非const版本不同。 C ++ 11 21.4.5“ basic_string
element access”說:
const_reference operator[](size_type pos) const; reference operator[](size_type pos);
需要:
pos <= size()
。返回:
*(begin() + pos
)如果pos < size()
,否則引用類型為T的對象,其值為charT()
; 參考值不得修改。
因此,對於C ++ 11編譯器,無論string
是否為const
,行為都是明確定義的。
與這個問題無關,我發現C ++ 11說“引用的值不會被修改”有點奇怪 - 我不清楚該子句是否僅適用於pos == size()
。 我很確定有大量的現有代碼可以執行s[i] = some_character;
其中s
是非const std:string
, i < s.size()
。 這是不確定的行為嗎? 我懷疑該子句僅適用於特殊情況的charT()
對象。
另一個有趣的事情是,兩個標准似乎都不要求為s[s.size()]
返回的對象的地址與s[s.size() - 1]
返回的對象的地址有任何關系。 換句話說,似乎返回的charT()
引用不必與字符串數據的末尾連續。 我懷疑這是為了給實現者提供一個選擇,如果需要,只返回對該Sentinel元素的單個靜態副本的引用(這也解釋了C ++ 11的“不應修改”限制,假設它僅適用於特殊案件)。
reference operator[]( size_type pos ); const_reference operator[]( size_type pos ) const;
如果
pos==size()
,
- const版本返回對值為CharT()(空字符)的字符的引用。 (直到C ++ 11)
- 兩個版本都返回對值為CharT()(空字符)的字符的引用。 通過非const引用修改空字符會導致未定義的行為。 (自C ++ 11以來)
只要你不修改空字符就可以了。
如果你想這樣做(你的同事的代碼試圖復制終止\\0
)你可以
c_str()
。 i < s.size()
的循環,然后手動追加\\0
。 編輯:
那么,從其他答案判斷,我更傾向於認為Abyx的評論是正確的:數組d
可能溢出(或者甚至可能沒有分配)。 先檢查一下。
但是要確保你復制\\0
!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.