簡體   English   中英

對於std :: string使用operator []是否安全

[英]Is it safe to use operator [] for std::string

我正在與舊的C風格界面作斗爭。 我有一個像這樣的簽名功能:

 /// if return_value == NULL only the length is returned
 void f( char * return_value, size_t * size_only_known_at_runtime); 

我的問題是,以下代碼是否安全?

std::size required;
f( NULL, &required );
std::string s;
s.resize(required);
f( &s[0], &required );

有沒有更好的方法將數據輸入字符串?

是的,它是安全的,至少從C ++ 11中是明確的。 來自[string.require],強調我的:

basic_string對象中的char類對象應連續存儲 即,對於任何的basic_string對象s時,身份&*(s.begin() + n) == &*s.begin() + n應的所有值保持n使得0 <= n < s.size()

這是DR 530的解決方案。 在C ++ 11之前,這在標准中並不明確,盡管無論如何它都是在實踐中完成的。

在C ++ 14中,此要求已移至[basic.string]:

basic_string是一個連續的容器(23.2.1)。

where [container.requirements.general]:

連續容器是一個支持隨機訪問迭代器(24.2.7)的容器,其成員類型iteratorconst_iterator是連續迭代器(24.2.1)。

其中[iterator.requirements.general]:

迭代器進一步滿足以下要求:對於整數值n和可解除引用的迭代器值a(a + n)*(a + n)等價於*(addressof(*a) + n) ,稱為連續迭代器

問題是代碼是否存在

std::size_t required_size;
f( nullptr, &required_size );
std::string s;
s.resize( required_size );
f( &s[0], &required_size );

是安全的。

這取決於假設哪個C ++標准,但由於在C ++ 03和C ++ 98中對於required_size = 0的情況它是未定義的行為,一般的答案是否定的 ,一般來說它不安全。


在C ++ 03中, std::string沒有正式保證有一個連續的緩沖區,但實際上所有現存的實現都有連續的緩沖區。 無論如何,現在在C ++ 11之后,連續緩沖區保證正式合並到標准中,將不會出現任何具有非連續緩沖區的新C ++ 03實現。 因此,這不是問題。

問題在於,在C ++ 03中, std::basic_string::operator[]定義如下:

C ++03§21.3.4/ 1

返回:如果pos < size() ,則返回data()[pos] 否則,如果pos == size() ,則const版本返回charT() 否則,行為未定義。

因此,對於非const字符串s大小為0,在C ++ 03它是未定義行為™做索引s[0]

在C ++ 11中,相應的段落§21.4.3/ 2表示如果pos < size()則結果是“ *(begin() + pos) pos < size() ,否則引用值為charT()的類型為T的對象; 參考值不得修改。“


無論編譯器實現哪種C ++標准,這里的代碼都有效:

 std::size_t required_size; f( NULL, &required_size ); // Establish required buffer size. if( required_size > 0 ) { std::string s( required_size, '#' ); f( &s[0], &required_size ); s.resize( strlen( &s[0] ) ); } 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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