最近在看《Effective STL》【条款17:使用交换技巧修整过剩容量】中提到容器的成函数void swap(container& from),即实现容器对象与from对象的交换。

另外,对于连续内存容器vector和string,还有shrink to fit(收缩到合适,根据容器的实际size设置capacity,减少实际内存分配)的功能。

以vector为例,首先说下,size和capacity、resize和reserve的含义及区别。

1. sizecapacityresizereserve

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. swapshrink 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技巧的更多相关文章

  1. 利用swap技巧去除容器多余的容量

    假设我们预先为容器添加了一部分元素,接着用clear将它们删除,容器内部分配的存储空间实际上不会减小,改变的只是能够访问的元素个数.如下所示: std::vector<int> vec; ...

  2. copy and swap技巧与移动赋值操作符

    最近在实现一个Delegate类的时候碰到了一个问题,就是copy and swap技巧和移动赋值操作符有冲突. 比如有以下一个类: class Fun { public: Fun(const Fun ...

  3. [CPP] STL 简介

    STL 即标准模板库(Standard Template Library),是 C++ 标准库的一部分,里面包含了一些模板化的通用的数据结构和算法.STL 基于模版的实现,因此能够支持自定义的数据结构 ...

  4. c++ stl swap

    好久没写了,简单水一下吧! 一个是最近没怎么刷题,圣诞,元旦,leetcode暂停的比赛两周,自己最近沉迷于打游戏,没有好好抓住时间. 其实最近看了一点书,是侯捷的 <stl源码剖析>,有 ...

  5. CPP STL学习笔记

    STL的概念 源地址  https://www.ev0l.art/index.php/archives/15/ <li> Iterator (迭代器)<li> Containe ...

  6. 【S17】使用“swap技巧”除去多余的容量

    1.考虑下面的需求,对于vec开始的时候有1000个元素,后来只有10个元素,那么vec的capacity至少还是1000,后面的990个内存单元,没有使用,但是还被vec霸占着.如何释放这些内存呢? ...

  7. [CPP - STL] functor刨根问底儿

    作为STL六大组件之一,在STL源代码及其应用中,很多地方使用了仿函数(functor),尤其在关联型容器(如set.map)以及algorithm(如find_if.count_if等)中.虽然已经 ...

  8. 【转】[STL]vector和deque的内存释放(clear)

    vector的clear成员函数可以清除vector中的元素,使其大小减至0.但它却不能减小vector占用的内存. [cpp] view plain copy int main() { vector ...

  9. Effective STL

    第9条:慎重选择删除元素的方法 删除特定值元素,vector.string.deque用erase-remove:c.erase(remove(c.begin(),c.end(),1963),c.en ...

随机推荐

  1. Python内置函数和匿名函数

    内容回顾: 1.列表推导式 [变量(加工后的变量) for 变量 in iterable] 循环模式 [变量(加工后的变量) for 变量 in iterable if 条件] 筛选模式 生成器表达式 ...

  2. idea没有subversion问题

    问题描述:idea导入svn项目,但点击项目文件右键没有找到subversion选项.同时,idea界面底部没有version control菜单. 解决方法:原因是idea没有启动版本控制.点击id ...

  3. commons-lang3-RandomUtils

    随机工具类   RandomUtils nextBoolean() 返回一个随机boolean值 nextBytes(int count) 返回一个指定大小的随机byte数组 nextDouble() ...

  4. 初学ElasticSeacher

    这周,刚接手了同事那边的工作,项目里需要用到ElasticSeacher.但是,之前从未接触过,因此,看了ES的文档,开始慢慢的知道了一些ES的知识. 一.ES简介: Elasticsearch是一个 ...

  5. openssl转换各种证书的语法收集

    参考网址:https://www.sslshopper.com/ssl-converter.html 个人总结:先找准要生成什么证书先,尤其是正规购买的流程与openssl生成的不一样,所以先确定是什 ...

  6. Maven的构建配置文件(Build Profiles)

    在命令行使用构建配置文件时,是-P,比如:mvn -Pinput 注意:这里的构建配置文件并不是一个真正的文件,而是通过指定参数来做特定的事. 以下内容引用自https://ayayui.gitboo ...

  7. hive界面工具SQL Developer的安装;使用sql developer连接hive;使用sql developer连接mysql

    需要oracle帐号登录后下载 1.下载: http://www.oracle.com/technetwork/developer-tools/sql-developer/downloads/inde ...

  8. 关于Label::createWithBMFont中资源文件使用的坑爹问题解决方式

    1.问题 使用Label的createWithBMFont,结果.fnt的资源总是找不到或者获取数据失败.原来.fnt资源的使用须要配合该资源的.png共同 使用,如bitmapFontTest3.f ...

  9. windown vs2012 编译ffplay

    自己写的播放器播放有些文件出现问题,但ffplay播放都很正常,为方便调试,将ffplay.c编译成可执行文件. 一. 环境搭建 环境搭建前面已经有文章介绍,没有特殊的地方,不再赘述. 二.修改con ...

  10. 开关电路_MOS和三极管

    https://blog.csdn.net/acelit/article/details/70171312 绍过一般的电源开关电路,控制电源的目的是省电,控制静态电流.不过以下的电路存在着几个缺点:  ...