[CPP - STL] swap技巧
最近在看《Effective STL》,【条款17:使用“交换技巧”修整过剩容量】中提到容器的成函数void swap(container& from),即实现容器对象与from对象的交换。
另外,对于连续内存容器vector和string,还有shrink to fit(收缩到合适,根据容器的实际size设置capacity,减少实际内存分配)的功能。
以vector为例,首先说下,size和capacity、resize和reserve的含义及区别。
1. size和capacity、resize和reserve
size:对象的元素个数,除reserve外的几乎所有vector操作都可以影响size;
capacity:容器预留容量,即占用真实内存量,capacity >= size。push_back、insert、resize、reserve操作可以影响capacity,其特点为只增不减(即使erase和clear操作);
resize:可以改变size,如果resize的元素个数大于capacity,则同时改变capacity,增加对象内存空间;
reserve:不改变size,如果reserve的元素个数大于capacity,则改变capacity,增加对象内存空间,反之,则不影响capacity;
代码示例如下:
#include <iostream>
#include <vector> using namespace std; int main()
{
vector<int> v;
cout << "initial: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.insert(v.end(), , );
cout << "after insert: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.erase(v.end()-, v.end());
cout << "after erase: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.reserve();
cout << "after reserve: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.resize();
cout << "after resize: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.reserve();
cout << "after reserve: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.clear();
cout << "after clear: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; return ;
}
输出结果为:
initial:
size of v is
capacity of v is after insert:
size of v is
capacity of v is after erase:
size of v is
capacity of v is after reserve:
size of v is
capacity of v is after resize:
size of v is
capacity of v is after reserve:
size of v is
capacity of v is after clear:
size of v is
capacity of v is
根据上面几个概念及Demo,可以看出来,vector对象的实际内存(即capacity)在多次insert和erase操作后大于实际元素个数(size),即使在clear操作后,capacity依然不会减小为零。
所以,有必要对这种基于内存池的容器做内存收缩。
2. swap:shrink to fit
修改vector对象多余内存空间的方法:
vector<int>(v).swap(v); // v为一个vector对象
vector<int>(v)基于v拷贝构造了一个临时vector,其分配了v.size()个元素的内存空间,即capacity为v.size(),然后vector<int>(v)与v交换数据,交换后,v的capacity也减少为v.size(),而临时vector对象vector<int>(v)被销毁。
另外,vector<int>().swap(v); // 可以清除v的内存空间
代码示例如下:
#include <iostream>
#include <vector> using namespace std; int main()
{
vector<int> v(, );
cout << "initial: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; v.erase(v.end()-, v.end());
cout << "after erase: " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; vector<int>(v).swap(v);
cout << "after swap (shrink to fit): " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; vector<int>().swap(v);
cout << "after swap (clear): " << endl;
cout << "size of v is " << v.size() << endl;
cout << "capacity of v is " << v.capacity() << endl << endl; return ;
}
输出结果为:
initial:
size of v is
capacity of v is after erase:
size of v is
capacity of v is after swap (shrink to fit):
size of v is
capacity of v is after swap (clear):
size of v is
capacity of v is
如果使用C++11及更新标准的话,可以直接使用shrink_to_fit函数。
[CPP - STL] swap技巧的更多相关文章
- 利用swap技巧去除容器多余的容量
假设我们预先为容器添加了一部分元素,接着用clear将它们删除,容器内部分配的存储空间实际上不会减小,改变的只是能够访问的元素个数.如下所示: std::vector<int> vec; ...
- copy and swap技巧与移动赋值操作符
最近在实现一个Delegate类的时候碰到了一个问题,就是copy and swap技巧和移动赋值操作符有冲突. 比如有以下一个类: class Fun { public: Fun(const Fun ...
- [CPP] STL 简介
STL 即标准模板库(Standard Template Library),是 C++ 标准库的一部分,里面包含了一些模板化的通用的数据结构和算法.STL 基于模版的实现,因此能够支持自定义的数据结构 ...
- c++ stl swap
好久没写了,简单水一下吧! 一个是最近没怎么刷题,圣诞,元旦,leetcode暂停的比赛两周,自己最近沉迷于打游戏,没有好好抓住时间. 其实最近看了一点书,是侯捷的 <stl源码剖析>,有 ...
- CPP STL学习笔记
STL的概念 源地址 https://www.ev0l.art/index.php/archives/15/ <li> Iterator (迭代器)<li> Containe ...
- 【S17】使用“swap技巧”除去多余的容量
1.考虑下面的需求,对于vec开始的时候有1000个元素,后来只有10个元素,那么vec的capacity至少还是1000,后面的990个内存单元,没有使用,但是还被vec霸占着.如何释放这些内存呢? ...
- [CPP - STL] functor刨根问底儿
作为STL六大组件之一,在STL源代码及其应用中,很多地方使用了仿函数(functor),尤其在关联型容器(如set.map)以及algorithm(如find_if.count_if等)中.虽然已经 ...
- 【转】[STL]vector和deque的内存释放(clear)
vector的clear成员函数可以清除vector中的元素,使其大小减至0.但它却不能减小vector占用的内存. [cpp] view plain copy int main() { vector ...
- Effective STL
第9条:慎重选择删除元素的方法 删除特定值元素,vector.string.deque用erase-remove:c.erase(remove(c.begin(),c.end(),1963),c.en ...
随机推荐
- Codeforces 696E ...Wait for it...(树链剖分)
题目链接 ...Wait for it... 考虑树链剖分. 对于树上的每个点开一个set,记录当前该节点上所有的girls. 每个节点初始的权值为set中的最小值. 询问的时候每次在路径上寻找最小 ...
- git history 记录(上传到 issu-170 )
一.上传到gitlab 本地issu-170落后git很多,发生冲突的要手动修改. 2000 cd robot_demo_0226_ws/ 2001 ls 2002 cd IGV01-SW-170 2 ...
- Android 源码编译记录
问题1:Can't locate Switch.pm in @INC (you may need to install the Switch module) (@INC contains: /etc/ ...
- 【转载】GitHub中国区前100名到底是什么样的人
转载了这篇文章: http://www.jianshu.com/p/d29cba7934c9 这篇文章真是太牛了!转载过来涨涨见识,同时好好励志一把.还有,ruanyifeng怎么长那样... 哈 另 ...
- [Algorithom] Stack Data Structure in JavaScript
A stack is a collection of items that obeys the principle of "last in, first out". Like a ...
- mysql delete auto_increment列时的注意问题
1. 说明 在对带有AUTO_INCREMENT列的表delete掉所有数据时: (1)对于MyISAM表,在delete表中所有数据时没有任何风险,随意折腾: (2)对于InnoDB表,在delet ...
- C 标准库 - <signal.h>
C 标准库 - <signal.h> 简介 signal.h 头文件定义了一个变量类型 sig_atomic_t.两个函数调用和一些宏来处理程序执行期间报告的不同信号. 库变量 下面是头文 ...
- Irrlicht 3D Engine 笔记系列之 教程4 - Movement
作者: i_dovelemon 日期: 2014 / 12 / 16 来源: CSDN 主题: Event Receiver, Animator, Framerate independent move ...
- Android 学习之逐帧动画(Frame)
帧动画就是将一些列图片.依次播放. 利用肉眼的"视觉暂留"的原理,给用户的感觉是动画的错觉,逐帧动画的原理和早期的电影原理是一样的. a:须要定义逐帧动画,能够通过代码定义.也能够 ...
- Andriod三步学会安卓自己定义视图及其属性
第一步:自己定义属性 第二步:自己定义控件解析属性 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcm5adW9adW8=/font/5a6L5L2T/fo ...