当前位置: 首页 > article >正文

C++的STL_swap trick和现代C++的方法

在**《effective STL》**中:

Item 17:使用“the swap trick”来削减过剩的容量 Use “the swap trick” to trim excess
capacity 由于vector的复制构造函数只为被复制的vector分配它所需要的空间,故可以用如下的方式来削减vector
v中过剩的容量:vector(v).swap(v)

熟读《effective STL》的你一定听过STL_swap trick。这是一种及时释放内存的重要方法。

什么是STL_swap trick

我们都知道,std::vector的内存增长是随着元素的增加自动增加的,但是std::vector却没有相应的随着元素的减少自动释放内存的逻辑。因此,假设我们有下面的这样的类:
class CMyDataManger{
std::vector m_data;
//…
void Clear() {
m_data.clear();//这样写,m_data的内存是不会释放的,
// 假设data占用了大量的内存,那么我们就达不到释放内存的目的
}
};
在C99时代,如果要正确释放内存,我们需要这样写:
class CMyDataManger{
std::vector m_data;
//…
void Clear() {
std::vector().swap(m_data); // 把一个临时的空的vector和m_data的内存交换,
// 这样,在函数返回时,临时的vector析构,释放原来m_data的内存。
}
};
这个技巧在很长时间里都被C++社区津津乐道,在很多开源项目里也能看到这类技巧的实践。
实际上,这不是什么值得骄傲的事情,只能说C++ STL在很长时间没能满足开发者的相应诉求,只能通过一些隐晦的技巧进行实践。

现代C++的方法

终于,到了C++11,vector引入了shrink_to_fit()成员函数,通过这个函数向容器发起一个非约束性的请求,让容器的容量减少到当前大小,这个函数同样加入到了std::string和std::deque等其他容器类型。这才让STL_swap trick失去了实践价值。
在C++11以后的版本中,上述代码应该改为:
class CMyDataManger{
std::vector m_data;
//…
void Clear() {
m_data.clear();
m_data.shrink_to_fit();//释放内存
}
};
这样,代码可读性大大增加,代码的意图不释自明。

非约束性的请求

细心的你发现上面的“非约束性的请求”修饰词,那么,什么是“非约束性的请求”呢?
“非约束性的请求”就是指请求不一定被满足,而且我也不会告诉你请求是否满足,我具体怎么做,我自己决定。

这个词的解释看上去很有深奥,落实到代码里,其实就是说shrink_to_fit的返回值是void,shrink_to_fit根据内部的状态和策略自己决定是否执行内存释放,而且我是否执行对后续所有逻辑不会产生影响。

为什么要这么做呢,这也是出于性能考虑设计的。
例如,当前元素的占用空间比实际内存只少了几个字节,如果重新申请内存把现在的元素拷贝过去需要消耗大量性能的,这样做非常不划算,所以即使你让我shrink_to_fit,我也不会去做。但是对于当前实际使用空间远小于我已经申请的内存空间,那么还是会马上释放内存。

但是在日常逻辑开发时,大家不要写“非约束性的请求”的函数,而是在函数执行成功就返回true,执行失败就返回false,调用者不要忽略返回值,这样才能确保逻辑上的正确。
“非约束性的请求”的应用场景是“是否执行成功对后续所有逻辑不会产生影响”才能使用。

结语:

今天,我们一起复习了《effective STL》的一个知识点,《effective STL》是 2001年出版的Scott Meyers大师Effective三部曲之一,内容非常经典,但是20多年过去了,也有不少内容需要修订和进化。阅读经典著作,既要考虑当时特定的历史背景,也要汲取高超的技巧和思路,同时也要思考现代C++更好的实践,才能发挥出经典著作的现代实用价值。


http://www.kler.cn/a/449981.html

相关文章:

  • 微机接口课设——基于Proteus和8086的打地鼠设计(8255、8253、8259)
  • 12寸半导体厂等保安全的设计思路
  • linux socket编程之udp_dict_serve服务端--引入配置文件
  • 安卓从Excel文件导入数据到SQLite数据库的实现
  • 0009.基于springboot+layui的ERP企业进销存管理系统
  • UE5 猎户座漂浮小岛 12 技能 瞬移 重力控制
  • leetcode hot100 轮转数组
  • 深度学习之超分辨率算法——SRCNN
  • Visual Studio 、 MSBuild 、 Roslyn 、 .NET Runtime、SDK Tools之间的关系
  • 【Java基础面试题022】什么是Java内部类?有什么作用?
  • Qt笔记-Qt Creator开发环境搭建
  • C#(委托)2
  • 放弃机器学习框架,如何用Python做物体检测?
  • 监控MySQL数据表变化:Binlog的重要性及实践
  • 自建MD5解密平台-续
  • mysql中局部变量_MySQL中变量的总结
  • 【YashanDB知识库】Oracle pipelined函数在YashanDB中的改写
  • 蓝桥杯练习生第四天
  • Blazor 直接读取并显示HTML 文件内容
  • VSCode如何修改默认扩展路径和用户文件夹目录到D盘
  • 关于mac—address
  • linux安装宝塔面板及git
  • 基于Spring Boot的个性化推荐外卖点餐系统
  • HarmonyOS(72)事件拦截处理详解
  • Certifying LLM Safety against Adversarial Prompting
  • 网络管理 详细讲解