8

模板类中的许多方法都vector采用对对象的 const 引用value_type,例如:

void push_back (const value_type& val);

while通过值resize获取其value_type参数:

void resize (size_type n, value_type val = value_type());

作为一个非专业的 C++ 程序员,我只能想到这种选择的缺点(例如,如果size_of(value_type)足够大,可能会发生堆栈溢出)。因此,我想问对语言有更深入了解的人:

这种选择背后的设计原理是什么?

4

2 回答 2

9
void resize( size_type count, T value = T() );

此函数已从C++11 中删除。

C++11 有两个重载resize()

void resize( size_type count );
void resize( size_type count, const value_type& value);

这很容易理解。第一个在调整大小时使用默认构造的类型对象value_type来填充向量,第二个在调整大小时使用一个值来制作副本。

于 2013-05-15T16:05:36.410 回答
6

这似乎是一个设计缺陷,现已修复。

引用STL 缺陷 679

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);
于 2013-05-15T16:12:59.190 回答