簡體   English   中英

將C ++ 11 std :: string :: operator []返回以null結尾的緩沖區

[英]Will C++11 std::string::operator[] return null-terminated buffer

我有一個std::string類的對象,我需要傳遞給C函數,通過迭代它並搜索空終止符號來操作char*緩沖區。

所以,我有這樣的事情:

// C function
void foo(char* buf);

// C++ code
std::string str("str");
foo(&str[0]);

假設我們使用C ++ 11,因此我們保證std::string表示將具有連續存儲的字符。

但我想知道是否有任何保證&str[0]將指向以\\0結尾的緩沖區? 是的,有c_str成員函數,但我在談論operator[]

有人可以引用標准嗎?

在實踐中,是的。 std::string實現正好是符合標准的,不會在緩沖區的末尾存儲NUL字符。

所以,如果你不想知道這個想法,你就完成了。

但是,如果您想知道該標准是否為abtruse:


在C ++ 14中,是的。 明確要求[]返回一組連續的元素, [size()]必須返回一個NUL字符,而const方法可能不會修改狀態。 因此*((&str[0])+size())必須與str[size()] ,並且str[size()]必須是NUL,因此游戲結束。


在C ++ 11中,幾乎可以肯定。 有一些規則, const方法可能無法修改狀態。 可以保證data()c_str()返回一個以空值終止的緩沖區,該緩沖區在每個點都與[]一致。

對C ++ 11標准進行復雜的閱讀會說明在調用data()c_str()[size()]不會在緩沖區的末尾返回NUL終止符,而是返回static const CharT單獨存儲,緩沖區具有NUL應該是的單位化(甚至是陷阱值)。 由於要求const方法不能修改狀態,我認為這種讀數是不正確的。

這要求&str[str.size()].data()調用之間發生變化,這是一個const調用中string狀態的可觀察變化,我認為這是非法的。

繞過標准的另一種方法可能是不初始化str[str.size()]直到您通過調用.data() .c_str()或實際將str.size()傳遞給operator[]來合法訪問它。 由於除了標准中的那些元素之外沒有定義的方法來訪問該元素,因此您可以擴展並說NUL的延遲初始化是合法的。

我對此提出質疑,因為.data()的定義暗示[]的返回值是連續的,因此&[0].data().data()+.size()地址相同保證指向NUL CharT所以必須(&[0])+.size() ,並且沒有非const方法調用std::string的狀態可能不會在調用之間改變。

但是,如果編譯器可以看到並且看到你永遠不會調用.data().c_str() ,那么如果可以證明你從未調用它們,那么連續性的要求是否成立呢?

在這一點上,我舉起手來射擊敵對的編譯器。


這個標准非常被動地表達出來。 因此,可能有一種方法可以使符合std::string符合這些規則。 並且由於保證越來越接近明確要求那里的NUL終結符,因此新編譯器出現的使用C ++的折磨讀取聲稱符合標准的可能性很低。

根據標准,是的。 可以使用string::datastring::c_str訪問底層char容器,標准上說:

21.4.7.1 basic_string訪問器[string.accessors]
const charT* c_str() const noexcept;
const charT* data() const noexcept;

1 返回:指針p ,使得p + i == &operator[](i)[0,size()]每個i
2 復雜性:恆定時間。
3 要求:程序不得更改存儲在字符數組中的任何值。

並且為了證明它是空終止的,看一下operator[]定義(強調我的):

21.4.5 basic_string元素訪問[string.access]
const_reference operator[](size_type pos) const;
reference operator[](size_type pos);

1 要求: pos <= size().
2如果pos < size()返回: *(begin() + pos) pos < size() 否則,返回對charT類型的對象的引用,其值為charT() ,其中修改對象會導致未定義的行為。
3 投擲 :沒什么。
4 復雜性 :恆定時間。

因此operator[size()]返回charT() ,因為std::stringstd::basic_string<char>charT()'\\0'

這意味着,在您的情況下, *(&str[0] + str.size()) == '\\0'應根據標准始終為true


請注意,修改operator[size()]是UB。

暫無
暫無

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

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