我正在将一些数据从流中复制到一个字符串中,所以我考虑使用实际的字符数来调整字符串的大小,再添加一个用于终止字符串的字符串,如下所示:
std::istringstream stream { "data" };
const std::size_t count = 4;
std::string copy;
copy.resize(count + 1);
stream.read(©[0], count);
copy[count] = 0;
但是,在这种情况下,copy
表示其大小为5
(自从我调用resize(5)
以来一致)。这是否意味着resize()
会添加额外的终止字符本身?这意味着我不必担心在调用\0
后附加read(&data[0], count)
?
答案 0 :(得分:4)
来自标准的引用§21.4.7.1basic_string访问者[string.accessors] 表示std::string
具有保证的空终止缓冲区。
另外根据标准§21.4.4/ 6-8 basic_string capacity [string.capacity]:
void resize(size_type n, charT c);
6
需要:n <= max_size()
7
如果length_error
则抛出n > max_size()
。
8
效果:更改*this
指定的字符串的长度,如下所示:- 如果
n <= size()
,该函数将*this
指定的字符串替换为长度为n
的字符串,其元素是指定的原始字符串的初始元素的副本*this
。- 如果
n > size()
,该函数会将*this
指定的字符串替换为长度为n
的字符串,其第一个size()
元素是原始文件的副本由*this
指定的字符串,其余元素全部初始化为c
。
void resize(size_type n);
9
效果:resize(n,charT())
。
解释上面的std::string::resize
不会影响字符串缓冲区的终止空字符。
现在你的代码:
语句std::string copy;
定义一个空字符串(即copy.size() == 0
)。
语句copy.resize(count + 1);
,因为(n == 5) > 0
将使用填充\0
的长度为5的字符串替换副本(即空字符)。
现在声明stream.read(©[0], count);
std::stream::read
只会复制一个数据块,而不会检查其内容,也不会在末尾添加空字符。
换句话说,它只会将copy
的前4个空字符替换为“data”。 copy
的大小不会改变,它仍然是一个5大小的字符串。也就是说,copy
缓冲区的内容将是“data \ 0 \ 0”。
因为copy[count] = 0;
已经copy[4]
,所以调用\0
是多余的。但是,您的字符串不是“数据”,而是“数据\ 0”。
答案 1 :(得分:3)
不,你不必。 string
类抽象出“空终止字符序列”的概念,因此您不必再担心它了。
此外,返回的字符串的大小不计算终止字符,这与我提到的行为一致,因为如果您不必处理终止字符,则无需了解它。您的字符串只是您想要操作的字符,而不关心与您的实际数据无关的“实用程序”字符。