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