std :: vector的resize方法背后的设计原理是什么?

Mas*_*ano 8 c++ stdvector

模板类中的许多方法都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)可能发生足够大的堆栈溢出).因此,我想对那些对语言有更深入了解的人提出这样的要求:

这个选择背后的设计理由是什么?

Naw*_*waz 9

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在调整大小时填充向量,第二个使用在调整大小时从中复制的值.

  • @Massimiliano:cplusplus对于C++教程来说是一个糟糕的坏网站:即使C++ 11签名也不正确.它缺少`const&`.**首选[cppreference.com](http://en.cppreference.com/w/cpp)cplusplus.com** (5认同)

tao*_*ocp 6

这似乎是一个设计缺陷,现在已经修复.

引用STL缺陷679

C++ 98标准指定容器中的一个成员函数通过值而不是const引用传递其参数(T):

void resize(size_type sz,T c = T());

这些事实多年来一直在反复讨论/辩论,这是第一次在C++ 98批准之前.按值传递此参数的基本原理是:

因此,保证自引用语句可以正常工作,例如:

 v.resize(v.size() + 1, v[0]);  
Run Code Online (Sandbox Code Playgroud)

然而,这个理由并不令人信服,因为push_back的签名是:

 void push_back(const T& x);
Run Code Online (Sandbox Code Playgroud)

并且push_back具有类似的语义来调整大小(追加).而push_back也必须在自引用案例中起作用:

 v.push_back(v[0]);  // must work
Run Code Online (Sandbox Code Playgroud)

传递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库中发布,没有我所知道的问题报告.

拟议决议:

改变23.3.3 [deque],p2:

class deque {
   ...
   void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)

更改23.3.3.3 [deque.capacity],第3页:

void resize(size_type sz, const T& c);  
Run Code Online (Sandbox Code Playgroud)

更改23.3.5 [list],p2:

class list {
   ...
   void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)

更改23.3.5.3 [list.capacity],第3页:

 void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)

改变23.3.6 [vector],p2:

class vector {
   ...
   void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)

更改23.3.6.3 [vector.capacity],第11页:

void resize(size_type sz, const T& c);
Run Code Online (Sandbox Code Playgroud)