将C++ 11 std :: string :: operator []返回以null结尾的缓冲区

Fro*_*art 5 c++ c++11

我有一个std::string类的对象,我需要传递给C函数,char*通过迭代它并搜索空终止符号来操作缓冲区.

所以,我有这样的事情:

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

// C++ code
std::string str("str");
foo(&str[0]);
Run Code Online (Sandbox Code Playgroud)

假设我们使用C++ 11,因此我们保证std::string表示将具有连续存储的字符.

但我想知道是否有任何保证&str[0]会指向缓冲区结束\0?是的,有c_str成员函数,但我在谈论operator[].

有人可以引用标准吗?

Yak*_*ont 7

在实践中,是的.std::string标准的实现完全没有 - 符合标准 - 不在缓冲区的末尾存储NUL字符.

所以,如果你不想知道这个想法,你就完成了.

但是,如果您想知道该标准是否为abtruse:


在C++ 14中,是的.有一个明确的要求是[]返回一组连续的元素,并且[size()]必须返回一个NUL字符,而const方法可能不会修改状态.所以*((&str[0])+size())必须是相同的str[size()],并且str[size()]必须是NUL,因此游戏结束.


在C++ 11中,几乎可以肯定.有些规则const可能无法修改状态.保证data()c_str()返回一个[]在每个点都同意的以null结尾的缓冲区.

的C++ 11标准的A旋绕读数将陈述之前的任何呼叫data()c_str(),[size()]不会在缓冲器的末端返回NUL终止而是static const CharT被单独地存储,并且缓冲器具有未初始化(或甚至陷阱值)NUL应该在哪里.由于要求const方法不修改状态,我认为这种读数不正确.

这需要&str[str.size()]调用之间变化.data(),这是在国家可观察到的变化string在一个const电话,我会读为非法.

另一种方式来解决该标准可能会不初始化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++的折磨读取声称符合标准的可能性很低.


Zer*_*ges 5

根据标准,是的.底层字符容器可以使用string::datastring::c_str使用哪个标准说:

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)用于每个iin [0,size()].
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 返回: *(begin() + pos) if pos < size().否则,返回对charT具有value 的类型对象的引用charT(),其中修改对象会导致未定义的行为.
3 投掷:没什么.
4 复杂性:恒定时间.

从而operator[size()]返回charT()并且由于std::stringIS std::basic_string<char>,charT()'\0'.

这意味着,在您的情况下,*(&str[0] + str.size()) == '\0'应始终按照标准true.


请注意,修改operator[size()]是UB.


归档时间:

查看次数:

498 次

最近记录:

9 年,2 月 前