vector的resize方法背后的设计原理是什么?
What is the design rationale behind the resize method of std::vector?
模板类vector
中的许多方法接受value_type
对象的const引用,例如:
void push_back (const value_type& val);
而resize
取其value_type
参数值:
void resize (size_type n, value_type val = value_type());
作为一个非专业的c++程序员,我只能想到这种选择的缺点(例如,如果size_of(value_type)
足够大,可能会发生堆栈溢出)。我想对更了解这门语言的人提出的问题是:
这个选择背后的设计原理是什么?
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
类型的默认构造对象来填充向量,第二个在调整大小时获取一个值来复制。
这似乎是一个设计缺陷,现在已经修复了。
引用STL缺陷679
c++ 98标准规定,容器中只有一个成员函数按值传递其形参(T),而不是通过const引用:
void resize(size_type sz, T = T());
这个事实多年来一直被反复讨论/争论,第一次甚至是在c++ 98被批准之前。按值传递该参数的基本原理是:
使自引用语句保证工作,例如:
v.resize(v.size() + 1, v[0]);
然而,这个基本原理并不令人信服,因为push_back的签名是:
void push_back(const T& x);
和push_back具有与resize (append)类似的语义。push_back也必须在自引用的情况下工作:
v.push_back(v[0]); // must work
按值传递T的问题是,它可能比按引用传递要昂贵得多。反之也成立,但是当它成立时,通常不那么引人注目(例如对于标量类型)。
即使有move语义可用,按值传递该参数的代价也会很高。例如,考虑vector>:
std::vector<int> x(1000); std::vector<std::vector<int>> v; ... v.resize(v.size()+1, x);
在按值传递的情况下,x被复制一次到参数resize。然后在内部,由于代码在编译时无法知道resize使vector增长了多少,因此通常将x从resize的形参第二次复制(而不是移动)到vector中的适当位置。
使用pass-by-const-reference,上面示例中的x只需要复制一次。在这种情况下,x有一个昂贵的复制构造函数,因此可以保存的任何副本都代表着显著的节省。
如果我们可以有效地处理push_back,那么我们也应该有效地处理resize。以引用参数为参数的大小调整已经在CodeWarrior库中编码和发布,据我所知没有任何问题报告。
提出解决方法:
Change 23.3.3 [deque], p2:
class deque { ... void resize(size_type sz, const T& c);
更改23.3.3.3 [deque。]能力,p3:
void resize(size_type sz, const T& c);
Change 23.3.5 [list], p2:
class list { ... void resize(size_type sz, const T& c);
更改23.3.5.3 [list.]能力,p3:
void resize(size_type sz, const T& c);
Change 23.3.6 [vector], p2:
class vector { ... void resize(size_type sz, const T& c);
更改23.3.6.3[向量]。能力,赛:
void resize(size_type sz, const T& c);
- 为不同配置设置MSVC_RUNTIME_LIBRARY的正确方法是什么
- C++避免重复声明的语法是什么
- 在C++中,将大的无符号浮点数四舍五入为整数的最佳方法是什么
- 实现无开销push_back的最佳方法是什么
- C++从另一个类访问公共静态向量的正确方法是什么
- "throw expression code" 1e7 >返回 d 是什么?投掷标准::overflow_error( "too big" ) : d;意味 着?
- C++中名称篡改的目的是什么
- 在 c++ 中拥有一组结构的正确方法是什么?
- 这个指针和内存代码打印是什么?我不知道是打印垃圾还是如何打印我需要的值
- 是什么阻止DOMTimerCoordinator::NextID进入无休止的循环
- 派生类销毁的最佳实践是什么
- 这个语法std::class<>{}(arg1, arg2) 在C++中是什么意思?
- 通过JNI传递数据数组的最快方法是什么
- "using namespace std;"在C++的作用是什么?
- 在两台机器之间进行时间戳的最佳c++chrono函数是什么
- 文件系统:复制功能的速度秘诀是什么
- 用常见虚拟函数实现的任意组合来实现派生类的正确方法是什么
- 使用QQuickFramebufferObject时同步数据的最佳方式是什么
- std::vector.resize()中的第二个参数是什么意思
- vector的resize方法背后的设计原理是什么?