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