c++ - strcpy用法 - “&s[0]”是否指向std:: string中的連續字符?




memset memcpy (4)

我正在做一些維護工作,遇到類似以下的事情:

std::string s;
s.resize( strLength );  
// strLength is a size_t with the length of a C string in it. 

memcpy( &s[0], str, strLength );

我知道使用&s [0]如果它是std :: vector會是安全的,但是這是std :: string的安全使用嗎?


代碼可能會起作用,但更多的是運氣而不是判斷,它會對實現做出無法保證的假設。 我建議確定代碼的有效性是無關緊要的,而它是一個毫無意義的複雜性,很容易簡化為:

std::string s( str ) ;

或者,如果分配給現有的std :: string對象,只需:

s = str ;

然後讓std :: string本身確定如何實現結果。 如果你要採用這種廢話,那麼你也可以不使用std :: string並堅持使用,因為你重新引入了與C字符串相關的所有危險。


使用安全。 我認為大多數答案都是正確的,但標準改變了。 引用C ++ 11標準, basic_string一般要求[string.require] ,21.4.1.5,說:

basic_string對像中的char類對象應連續存儲。 也就是說,對於任何basic_string對象,標識&*(s.begin()+ n)==&* s.begin()+ n應該適用於n的所有值,使得0 <= n <s.size ()。

在此之前,它說所有迭代器都是隨機訪問迭代器。 這兩個位都支持您的問題的使用。 (此外,Stroustrup顯然在他最新的書中使用它;))

在C ++ 11中進行此更改並非不太可能。 我似乎記得為vector添加了相同的保證,它也獲得了該版本非常有用的data()指針。

希望有所幫助。


根據C ++ 98/03標準,std :: string的分配不保證是連續的,但C ++ 11強制它。 在實踐中,我和Herb Sutter都不知道不使用連續存儲的實現。

請注意,即使在0長度字符串的情況下, &s[0]事物也始終保證可以通過C ++ 11標準工作。 如果使用str.begin()&*str.begin() ,則無法保證,但對於&s[0] ,標準將operator[]定義為:

返回*(begin() + pos)如果pos < size() ,否則引用類型為T的對象,其值為charT() ; 參考值不得修改

繼續, data()定義為:

返回:指針p ,使得p + i == &operator[](i)[0,size()]每個i

(注意範圍兩端的方括號)

注意 :預標準化C ++ 0x並不能保證&s[0]能夠使用零長度字符串(實際上,它是顯式未定義的行為),並且這個答案的舊版本解釋了這一點; 這已在以後的標準草案中修復,因此答案已相應更新。


無論內部字符串序列是否連續存儲在內存中,這通常都是不安全的。 除了連續性之外,還有許多其他實現細節與std::string對像如何存儲受控序列有關。

一個真正的實際問題可能如下。 std::string的受控序列不需要存儲為以零結尾的字符串。 但是,在實踐中,許多(大多數?)實現選擇將內部緩衝區超大1並將序列存儲為零終止字符串,因為它簡化了c_str()方法的實現:只返回指向內部緩衝區的指針,你完成了

您在問題中引用的代碼沒有做任何努力將零終止數據複製到內部緩衝區中。 很可能它根本不知道對於std::string這種實現是否需要零終止。 很可能它依賴於在resize後調用零填充零的內部緩衝區,因此實現為零終止符分配的額外字符可以方便地預先設置為零。 所有這些都是一個實現細節,這意味著這種技術取決於一些相當脆弱的假設。

換句話說,在某些實現中,您可能不得不使用strcpy而不是memcpy來強制數據進入受控序列。 在其他一些實現中,您必須使用memcpy而不是strcpy





c++03