2016-07-29 252 views
7

不同的std ::向量的std :: string并没有提供一个一元构造函数大小:std :: string(size,' 0')和s.resize(size)之间的区别?

std::string s(size); // ERROR 

是否有任何区别:

std::string s(size, '\0'); 

std::string s; 
s.resize(size); 

就其在常见实施方面的表现而言?

将调整大小将字符串初始化为全部为零的字符,还是将它留给未指定的值?

如果全零,是否有任何方法来构造给定大小的字符串,但留下未指定值的字符?

+0

什么是size,size是0? –

+1

@FirstStep:不,其中'size'是一些'size_t',它是'> 0'。 –

+0

那么你是否通过一个profiler来运行一些实现来衡量它们的性能? –

回答

4

有一个区别,如std::string s(size, '\0');,该字符串所需的所有内存可以一次分配。但是,对于第二个示例,如果size大于为小字符串优化存储的字符数量,则可能必须执行额外的分配,尽管这是实现定义的,并且在标准中关于此的肯定不会更高性能兼容的C++ 17实现。但是,第一个例子更加简洁,可能更高效,因此可能更可取。当调用s.resize(size);时,所有新字符将被初始化为char的默认构造函数,即'\0'。没有办法用未指定的值初始化string

+4

为什么在第二种情况下会有第二次分配?在这两种情况下,如果'size'大于SSO缓冲区,则会有一个分配。 – Praetorian

+0

出于同样的原因'make_unique()'更快,然后'new'调用并调用构造函数。在第一种情况下,所有内存'std :: string'需要可以一起分配。但是,在第二种情况下,'new'可能必须被调用两次。这是我定义的实现,我将阐明。 – DeepCoder

+6

*出于和'make_unique()'更快,然后'new'调用和调用构造函数* ...一样的原因,你在考虑'make_shared',因为'make_unique'应该没有区别。无论如何,我看到你假设默认构造'std :: string'会分配一次内存,这是非常不寻常的,但是允许的。但是,仍然认为有差别似乎是错误的。有*可能*是有区别的,但很可能不是,除非你考虑初始化一些变量为'0',然后改变它们,将它们初始化为'size'开头,这是一个区别。 – Praetorian

4

实际答案将基于实施,但我相当确信std::string s(size, '\0');更快。

std::string s; 
s.resize(size); 

根据documentation for std::string

1)默认构造函数。构造空字符串(零大小和未指定的容量)。

默认构造函数将创建一个“未指定容量”的字符串。我的感觉是,实现可以自由确定一个默认容量,可能在10-15个字符的范围内(完全推测)。

然后在下一行,你会重新分配新size内存(resize)如果size比当前更大capacity。这可能不是你想要的!

如果你真的想明确地找到,你可以在这两种方法上运行一个分析器。

2

DeepCoder已经有一个很好的答案。

然而,对于记录,我想指出的是字符串(作为载体),有两个不同的概念:

  • size():它的实际(即有意义的)中的字符数串。你可以使用resize()来更改它(如果它不应该是'\0',你可以提供第二个参数来说明你想用作填充符的字符)
  • capacity():它是分配给字符串的字符数。至少它的大小,但可以更多。你可以增加它reserve()

如果你担心分配表现,我相信最好玩的容量。大小应该真的保留字符串中的实际字符而不是填充字符。

顺便说一下,更一般地说,s.resize(n)s.resize(n, char())相同。所以如果你想在施工时以相同的方式填充它,你可以考虑string s(n, char())。但只要你不使用basic_string<T>使T与字符不同,你的'\ 0'就是这样做的。

1

调整大小不会使元素未初始化。根据文档:​​

s.resize(size)将对每个附加字符进行值初始化。这将导致调整大小的字符串的每个元素被初始化为'\0'

您将不得不衡量您特定C++实现的性能差异,以真正决定是否有值得区别。

查看由Visual C++生成的机器以获得优化版本后,我可以告诉您任一版本的代码量是相似的。看起来相反直观的是resize()版本测量更快对我来说。不过,你应该检查你自己的编译器和标准库。

相关问题