访问 std::string 中的空终止字符(字符串下标超出范围)

Posted

技术标签:

【中文标题】访问 std::string 中的空终止字符(字符串下标超出范围)【英文标题】:Accessing null-termination character in std::string (string subscript out of range) 【发布时间】:2013-08-18 13:32:35 【问题描述】:

考虑以下非常简单的文本示例:

#include <stdio.h>
#include <string>
int main() 
    std::string x("ugabuga");
    int i=0;
    while (x[i]) 
        ++i;
    
    printf("%d\n",i); //should print 7
    return 0;

我希望程序遍历字符串的所有字符,然后到达终止循环的空终止字符并正确到达程序结束。 但是,当我尝试在 Visual Studio 2010 下以调试模式编译它时,我遇到了一个异常“字符串下标超出范围”。 在发布模式下编译时,此程序通过,但我的更大项目取决于此行为崩溃 - 可能是因为这个问题。

但是,当我在www.cplusplus.com 处检查std::string::operator[] 的规范时,会显式处理结束字符串:

如果 pos 等于字符串长度,则函数返回对空字符 ('\0') 的引用。

我想在这里问一下:

我对@9​​87654324@ 规范的解释正确吗?还是我错过了什么? 如果问题出在实现的 VS 方面,我怎样才能轻松解决这个问题 - 希望每次使用 operator[] 时都无需调用 length()?例如使用c_str()[i] 会安全吗? 如果问题出在 VS 的实现方面 - 您是否知道它是否已在 VS 2012 中修复,或者将来可能会修复?

【问题讨论】:

【参考方案1】:

这是 C++03 和 C++11 之间发生变化的事情之一。

这似乎是 C++03 中未定义的行为:

21.3.4 basic_string 元素访问[lib.string.access]

const_reference operator[](size_type pos) const;

reference operator[](size_type pos);

1 返回:如果pos &lt; size(),则返回data()[pos]。否则,如果pos == size(),则为const version returns charT()。否则,行为未定义。

在 C++11 中是可以的。

21.4.5 basic_string 元素访问[string.access]

const_reference operator[](size_type pos) const;

reference operator[](size_type pos);

1 要求:pos

2 返回:*(begin() + pos) 如果pos &lt; size(),否则对类型为T 且值为charT(); 的对象的引用不应修改引用的值。

【讨论】:

因此 OP 的解决方案是使用常量引用进行迭代:const std::string &amp;cx = x; while (cx[i]) ... @rodrigo 这将使它定义为行为。我不知道 OP 试图解决什么问题,但我怀疑有问题的 while 循环只是理解某些东西的一种手段。否则只会使用x.size() 感谢您的澄清。你知道 VS 在实现这些方面有多远吗?回答您的问题:我正在循环中实现一个简单的解析器。识别字母、数字、空格和字符串结尾。 @CygnusX1 抱歉,我不确定您需要哪个版本的 VS 才能获取 C++11 字符串。但是你可以遍历索引[0, x.size()) VS C++ 2010 及更高版本似乎有一个 std::string 根据 C++11 标准提供对终止空字符的访问。

以上是关于访问 std::string 中的空终止字符(字符串下标超出范围)的主要内容,如果未能解决你的问题,请参考以下文章

使用类似 strndup 的语义从 char[] 创建 std::string

std::string 可以包含嵌入的空值吗?

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

将 std::string_view 与 api 一起使用,期望以 null 终止的字符串

什么是空终止字符串?

用向量的向量的元素初始化向量的空向量