模板类中的许多方法都vector接受value_type对象的const引用,例如:
void push_back (const value_type& val);
Run Code Online (Sandbox Code Playgroud)
while 按值resize获取其value_type参数:
void resize (size_type n, value_type val = value_type());
Run Code Online (Sandbox Code Playgroud)
作为一个非专业的C++程序员,我只能想到这个选择的缺点(例如,如果size_of(value_type)可能发生足够大的堆栈溢出).因此,我想对那些对语言有更深入了解的人提出这样的要求:
这个选择背后的设计理由是什么?
void resize( size_type count, T value = T() );
Run Code Online (Sandbox Code Playgroud)
此函数已从C++ 11中删除.
C++ 11具有两个重载的resize():
void resize( size_type count );
void resize( size_type count, const value_type& value);
Run Code Online (Sandbox Code Playgroud)
这很容易理解.第一个使用类型的默认构造对象value_type在调整大小时填充向量,第二个使用在调整大小时从中复制的值.
这似乎是一个设计缺陷,现在已经修复.
引用STL缺陷679
C++ 98标准指定容器中的一个成员函数通过值而不是const引用传递其参数(T):
void resize(size_type sz,T c = T());
这些事实多年来一直在反复讨论/辩论,这是第一次在C++ 98批准之前.按值传递此参数的基本原理是:
因此,保证自引用语句可以正常工作,例如:
Run Code Online (Sandbox Code Playgroud)v.resize(v.size() + 1, v[0]);然而,这个理由并不令人信服,因为push_back的签名是:
Run Code Online (Sandbox Code Playgroud)void push_back(const T& x);并且push_back具有类似的语义来调整大小(追加).而push_back也必须在自引用案例中起作用:
Run Code Online (Sandbox Code Playgroud)v.push_back(v[0]); // must work传递T值的问题在于它比通过引用传递要贵得多.反过来也是如此,但是当它成立时它通常远不那么引人注目(例如对于标量类型).
即使可用移动语义,按值传递此参数也很昂贵.考虑例如vector>:
Run Code Online (Sandbox Code Playgroud)std::vector<int> x(1000); std::vector<std::vector<int>> v; ... v.resize(v.size()+1, x);在pass-by-value的情况下,x被复制一次到resize的参数.然后在内部,由于代码在编译时无法知道向量增加了多少调整大小,因此x通常会第二次从resize的参数复制(不移动)到向量中的适当位置.
使用pass-by-const-reference,上例中的x只需复制一次.在这种情况下,x具有昂贵的复制构造函数,因此任何可以保存的副本都可以节省大量成本.
如果我们对push_back有效,那么我们也应该有效调整大小.采用参考参数的resize已经编码并在CodeWarrior库中发布,没有我所知道的问题报告.
拟议决议:
改变23.3.3 [deque],p2:
Run Code Online (Sandbox Code Playgroud)class deque { ... void resize(size_type sz, const T& c);更改23.3.3.3 [deque.capacity],第3页:
Run Code Online (Sandbox Code Playgroud)void resize(size_type sz, const T& c);更改23.3.5 [list],p2:
Run Code Online (Sandbox Code Playgroud)class list { ... void resize(size_type sz, const T& c);更改23.3.5.3 [list.capacity],第3页:
Run Code Online (Sandbox Code Playgroud)void resize(size_type sz, const T& c);改变23.3.6 [vector],p2:
Run Code Online (Sandbox Code Playgroud)class vector { ... void resize(size_type sz, const T& c);更改23.3.6.3 [vector.capacity],第11页:
Run Code Online (Sandbox Code Playgroud)void resize(size_type sz, const T& c);