在C++11中,修改由operator[]返回的内部std::string缓冲区是被允许的吗?

6

标准中是否有任何规则违反了对由 operator[] 返回的内部 std::string 缓冲区进行修改的更改,例如:

void foo(char* buf)
{
  buf[1] = 's';
}

std::string str = "str";
modify_buffer(&str[0]);

我在 C++11 草案中找到了有关 datac_str 函数的以下引用:

要求:程序不得更改存储在字符数组中的任何值。

但是我没有看到与 operator[] 相关的内容。

3
你的示例中没有使用std::string - aschepler
3
由于data()c_str()返回的是const char*,所以会产生这样的结果。 - DimChtz
@aschepler 抱歉,已修复。 - FrozenHeart
如果您可以使用operator[]修改内容,那么为什么认为指向元素的指针会有任何不同呢? - NathanOliver
1个回答

10

operator[]

operator[]返回对字符的引用。所以如果string不是const,你可以安全地修改它。

对于C++11,字符被连续存储,因此你可以将&str[0]作为其大小为str.size()的基础数组的开头。如果string不是const,你可以修改任何位于[ &str[0], &str[0] + str.size() )之间的元素。例如,你可以将&str[0]str.size()传递给void func(char * arr, size_t arr_size): func(&str[0], str.size())

data()c_str()成员

对于C++11和C++14,data()c_str()都返回const CharT*,因此你不能使用返回的指针修改元素。然而,在C++17中,如果string不是constdata()将返回CharT*data()将成为&str[0]的别名。


我不确定C11++是什么意思,但由于C11++并不是关于C++的唯一标准,所以我不会依赖于连续的数组元素被连续存储。通常情况下,为了分配连续的内存而进行存储是很昂贵的,因此将char元素存储在桶中是很常见的,因此不要期望它们都是连续的。我编写了一个具有与string相同语义但具有写时复制规范和仅到某个点连续的charString(请注意我不写string)。 - Luis Colorado
@for_stack,你能否在规范中提供一下你所说的“对于C++11”的段落中所述内容的参考资料?这听起来像是一个权威性的声明,能够看到它的来源会很好。谢谢! - bhaller
1
@bhaller 请查看此链接的第二段。 - for_stack
@for_stack,谢谢!它似乎只是对连续的存储做出了一个陈述 - 这是您的第一个声明。是否还有关于通过指针进行修改是合法的保证?即,保证std::string没有缓存字符串数据的各种属性,或者由于某种原因在内部复制数据,或者类似于此类的任何事情,以便不仅读取而且写入指针都是合法的?我想实际上它通常可以工作,但我想知道在C++11中是否有硬性保证。 - bhaller
从链接中:可以将指向s [0]的指针传递给期望CharT []数组的第一个元素的指针的函数。由于函数可以修改输入字符数组,因此您可以通过指针安全地修改字符串。 - for_stack

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接