这个问题是由以下来自how to pre-allocate memory for a std::string object?的代码片段引起的
file.seekg(0, std::ios::end);
s4.resize(file.tellg());
file.seekg(0, std::ios::beg);
file.read(&s4[0], s4.length());
在我看来,只有resize()
首先为null分配了一个额外的字节,才能保证正确(后续s4.data()
将返回长度为N,总大小为N+1字节的以null结尾的字符串)和有效(s4.data()
不需要进行额外的重新分配/复制)。
它确实这样做了吗?
3条答案
按热度按时间j0pj023g1#
C++标准([basic.string])规定,对于
std::basic_string<charT>
:data() + size()
指向具有值charT()
的对象(“空终止符”),此外,数据必须是连续的。因此,是的。在字符串数据之后总是分配一个终止字符,以使其成为有效的C字符串。
qlvxas9a2#
如果你在libstdc中查看
basic_string
的源代码,你可以看到这是在_M_create
函数中完成的:所以对于
libstdc
,是的,这已经完成了。但是否需要这样做完全取决于底层实现如何处理内存。例如,如果底层OS已经保证对于给定指针,在分配的存储器之后的访问将总是导致
\0
,则这将不是必需的。附带说明:
实现可以(并且这也是AFAIK针对小字符串优化部分完成的)使用包含关于字符串长度的信息的存储器,也用于空终止部分。
所以你可以有这样的东西:
数据可能是这样的:
[number of bytes equal to capacity][bytes required for storing length]
长度存储为
max_capacity-lenght_of_string
,因此如果字符串达到最大容量,则存储长度的字节将为0
,然后可以用作空终止,因此不需要为\0
分配额外的字节(仅为长度的字节)。r8xiu3jd3#
终止符不算作std::string中的元素
你也可以用正确的大小来初始化字符串
https://en.cppreference.com/w/cpp/io/basic_istream/read