在C++11中,将数据写入std::string的&str[0]缓冲区是否是良好定义的行为?

34
char hello[] = "hello world";
std::string str;
str.resize(sizeof(hello)-1);
memcpy(&str[0], hello, sizeof(hello)-1);

这段代码在C++98中是未定义的行为。在C++11中它是否合法?


4
std::string的新保证是其缓冲区连续存储。但我不确定标准是否允许写入该缓冲区,因为据我所知,std::string的COW实现仍然有可能存在。 - cubuspl42
1
你到底为什么想要这样做? - user3791372
8
有很多好的理由。例如:string str; str.resize(8); fread(&str[0], 1, str.size(), file); - cubuspl42
11
C++11 不允许使用 COW。参见此答案:https://dev59.com/hGct5IYBdhLWcg3wSrl3 - imreal
所以在我看来,你的代码没有理由出现未定义行为。 - imreal
1个回答

31

是的,这段代码在C++11中是合法的,因为std::string的存储被保证是连续的,并且您的代码避免了覆盖终止的NULL字符(或值初始化的CharT)。

来自N3337,《§21.4.5 [string.access]》

 const_reference operator[](size_type pos) const;
 reference operator[](size_type pos);

1 需求:pos <= size()

2 返回:如果pos < size(),则返回*(begin() + pos)。否则,返回一个类型为charT值为charT()的对象的引用,修改该对象会导致未定义的行为。

您的示例满足上述要求,因此行为是良好定义的。


#2返回的引用需要保持多长时间有效?引用是否需要指向连续的存储空间?也就是说,符合规范的实现是否可以返回对所请求位置的char的副本的引用,只要对它(以及它本身)的读写操作符合预期即可? - BCS
1
@BCS 引用将在字符串的生命周期内有效,或者直到您执行某些使引用(和迭代器)无效的操作,通常是调整字符串大小。除了上面引用的部分外,还请参阅 [string.accessors] 以获取 data() 成员函数的描述。通过这两个部分,就可以清楚地了解符合规范的实现需要具有连续的存储,并且 operator[] 返回对此存储中元素的引用。 - Praetorian

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