C++98 标准规定容器中的一个成员函数单独通过值而不是通过 const 引用传递其参数 (T):
void resize(size_type sz, T c = T());
多年来,这一事实已被反复讨论/辩论,第一次甚至在 C++98 被批准之前。按值传递此参数的基本原理是:
这样自引用语句就可以保证工作,例如:
v.resize(v.size() + 1, v[0]);
然而,这个理由并不令人信服,因为 push_back 的签名是:
void push_back(const T& x);
并且 push_back 具有类似的语义来调整大小(追加)。并且 push_back 也必须在自引用情况下工作:
v.push_back(v[0]); // must work
通过值传递 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 库中编码和发布,没有我知道的问题报告。
提议的决议:
更改 23.3.3 [deque],p2:
class deque {
...
void resize(size_type sz, const T& c);
更改 23.3.3.3 [deque.capacity],p3:
void resize(size_type sz, const T& c);
更改 23.3.5 [列表],p2:
class list {
...
void resize(size_type sz, const T& c);
更改 23.3.5.3 [list.capacity],p3:
void resize(size_type sz, const T& c);
更改 23.3.6 [向量],p2:
class vector {
...
void resize(size_type sz, const T& c);
更改 23.3.6.3 [vector.capacity],p11:
void resize(size_type sz, const T& c);