std::vector::resize
从 pre-C++11发生变化背后的原因是什么:
void resize( size_type count, T value = T() );
到兼容的 C++11 形式:
void resize( size_type count );
void resize( size_type count, const value_type& value);
C++11 标准的附件 C(兼容性)第 C.2.12 段规定:
更改:签名更改:
resize
基本原理:性能,与移动语义的兼容性。
对原始功能的影响:对于传递给 resize 的
vector
、deque
和list
填充值现在通过引用而不是按值传递,并且添加了额外的 resize 重载。使用此函数的有效 C++ 2003 代码可能无法使用此国际标准进行编译。
旧resize()
功能是从value
. resize()
当向量的元素是默认可构造但不可复制(您可能希望稍后移动分配它们)时,这使得它无法使用。这解释了“与移动语义的兼容性”的基本原理。
此外,如果您不希望发生任何复制,它可能会很慢,而只是默认构造新元素。此外,value
在 C++03 版本中,参数是按值传递的,这会产生不必要的副本的开销(正如 TemplateRex 在他的回答中提到的那样)。这解释了“性能”的基本原理。
一个原因是默认参数总是被传递,即在这种情况下被复制。正在做
my_vector.resize(1000000)
将复制 100 万个T
对象。
std::allocator_traits<Alloc>::construct()
在 C++11 中,您现在可以选择使用该函数复制用户提供的值或就地默认插入(即构造)元素。这允许vector
使用 CopyInsertable 但不可 Copyable 的元素调整大小。
请注意,此更改已针对所有具有resize()
成员(vector
、和)的序列容器进行deque
,但不适用于开头没有默认值参数的序列容器。forward_list
list
std::string
更新:除了@AndyProwl 引用的当前标准的附件外,@HowardHinnant 的原始缺陷报告还澄清了:
通过值传递 T 的问题在于它可能比通过引用传递更昂贵。反之亦然,但是当它为真时,它通常远没有那么引人注目(例如,对于标量类型)。
即使移动语义可用,按值传递此参数也可能很昂贵。考虑例如向量>:
std::vector<int> x(1000); std::vector<std::vector<int>> v; ...
v.resize(v.size()+1, x);
在按值传递的情况下,x 被复制一次到 resize 的参数中。然后在内部,由于代码在编译时无法通过调整大小来知道向量增长了多少,因此 x 通常会第二次从调整大小的参数复制(不移动)到向量中的适当位置。
使用 pass-by-const-reference,上例中的 x 只需复制一次。在这种情况下,x 有一个昂贵的副本构造函数,因此任何可以保存的副本都代表了显着的节省。
如果我们可以高效地 push_back,那么我们也应该高效地调整大小。采用参考参数的调整大小已在 CodeWarrior 库中编码和发布,没有我知道的问题报告。