[英]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::data
或string::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::string
是std::basic_string<char>
, charT()
是'\\0'
。
這意味着,在您的情況下, *(&str[0] + str.size()) == '\\0'
應根據標准始終為true
。
請注意,修改operator[size()]
是UB。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.