STL容器提供的是“value semantic”而非“reference semantic”。然而不论是为了降低元素过大的复制代价还是为了在不同集合中共用同一个元素的需求,这时我们必须使用“reference semantic”,方式有二:

使用智能指针

#include <string>
#include <iostream>
#include <memory>
#include <set>
#include <deque>
#include <algorithm>class Item
{
private:std::string _name;float _price;
public:Item(const std::string& name, float price):_name(name), _price(price){}std::string getName() const { return _name;}void setName(const std::string& name) { _name = name;}float getPrice() const { return _price;}void setPrice(float price) { _price = price;}
};template<typename Coll>
void printItems(const std::string& msg, const Coll& coll)
{std::cout << msg << std::endl;for (const auto& elem: coll)std::cout << " " << elem->getName() << ": " << elem->getPrice() << std::endl;
}int main(int, char**)
{typedef std::shared_ptr<Item> ItemPtr;std::set<ItemPtr> allItems;std::deque<ItemPtr> bestItems;bestItems = {ItemPtr(new Item("C++", 10.)), ItemPtr(new Item("Python", 20.))};allItems = {ItemPtr(new Item("Machine Learning", 30.))};allItems.insert(bestItems.begin(), bestItems.end());// 此时bestItems同时被两个容器所操纵// 而我们知道两种容器的更新应当是同步的printItems("bestItems: ", bestItems);printItems("allItems: ", allItems);std::cout << std::endl;// 将bestItems的售价都提高一倍std::for_each(bestItems.begin(), bestItems.end(), [](ItemPtr& elem){elem->setPrice(elem->getPrice()*2);});// 同时修改allItems,bestItems// 将bestItems[1]替换为“Machine Learning”bestItems[1] = *std::find_if(allItems.begin(), allItems.end(),[](ItemPtr elem){return elem->getName() == "Machine Learning";});bestItems[0]->setPrice(55.);printItems("bestItems: ", bestItems);printItems("allItems: ", allItems);return 0;
}

这里尤其注意一个隐蔽的细节:
对bestItems[1]进行替换时,使用set的find成员函数还是使用std::find()都无法实现需求,如:

find(allItems.begin(), allItems.end(), ItemPtr(new Item("Machine Learning", 30.)));
allItems.find(ItemPtr(nwe Item("Machine Learning", 30.)));

因为将allItems的内部元素和传递进来的new出来的智能指针作比较,是永远不会相等的,所以最终返回的Iterator是allItems.end(),无法提领其元素。

这里会存在一个问题,此时将bestItems销毁时,allItems中的相应元素不会被销毁,而会持续有效。

bestItems.clear();
printItems("allItems: ", allItems);

使用reference wrapper

假设保证“只要容器存在,被指向的元素一定存在”,就需使用另一种方法使用class reference_wrapper<>(位于<functional>头文件)。

typedef std::reference_wrapper<Item> ItemRef;
std::vector<ItemRef> books;// std::vector<Item&>,不允许
Item item1("C++", 20.);
books.push_back(item1);for (const auto& book: books)std::cout << book.get().getName() << ": " << book.get().getPrice() << std::endl;// 当声明其具体类型时,get()就不再必须
for (const Item& book: books)std::cout << book.getName() << ": " << book.getPrice() << std::endl;book.setPrice(29.99);
std::cout << books[0].get().getPrice() << std::endl;// 29.99
books[0].get().setName("C++ Primer");
std::cout << books[0].get().getName() << std::endl;// C++ Primer

C++STL::两种方式实现STL容器的reference语义相关推荐

  1. 根据官网文档看Spark Streaming对接Kafka的两种方式, 以及如何实现Exactly Once语义

    注: 本文算是本人的学习记录, 中间可能有些知识点并不成熟, 不能保证正确性. 只能算是对官网文档作了个翻译和解读, 随时有可能回来更新和纠错 上一篇文章讨论了Spark Streaming的WAL( ...

  2. docker容器运行mysql持久化_docker容器实现数据持久化的两种方式及其区别

    前言 这篇博文是我对docker实现数据持久化几种方式的特征进行一个总结. 在docker中,它的存储文件系统是在dockerhost上原有的xfs或ext4架设了一层文件系统:overlay2(将此 ...

  3. k8s 创建资源的两种方式 - 每天5分钟玩转 Docker 容器技术(124)

    命令 vs 配置文件 Kubernetes 支持两种方式创建资源: 1. 用 kubectl 命令直接创建,比如: kubectl run nginx-deployment --image=nginx ...

  4. apache http server 停止工作_Springboot以Tomcat为容器实现http重定向到https的两种方式

    1 简介 本文将介绍在Springboot中如何通过代码实现Http到Https的重定向,本文仅讲解Tomcat作为容器的情况,其它容器将在以后一一道来. 建议阅读之前的相关文章: (1) Sprin ...

  5. kubernetes创建资源的两种方式

    一.创建方式分类: 命令 vs 配置文件 Kubernetes 支持两种方式创建资源: 1.用 kubectl 命令行的方式直接创建,比如: kubectl run httpd-app --image ...

  6. maven生成war包的两种方式

    war包即对WEB应用程序进行打包,用于应用容器的部署.如在jboss中只要把war包丢入deploy目录下即可发布自己的应用了.打包方式有很多中,很多工具本身就支持此功能.下面主要介绍通过maven ...

  7. Spring Boot自定义 Servlet Filter 的两种方式

    点击上方蓝色"程序猿DD",选择"设为星标" 回复"资源"获取独家整理的学习资料! 作者 | 码农小胖哥 来源 | 公众号「码农小胖哥」 针 ...

  8. 【JetPack】视图绑定 ( ViewBinding ) 各种应用 ( 视图绑定两种方式 | Activity 布局 | 对话框布局 | 自定义组件布局 | RecyclerView 列表布局 )

    文章目录 I . 视图绑定 ( ViewBinding ) 界面的两种方式 II . Activity 界面中 应用 视图绑定 ( ViewBinding ) III . Dialog 对话框界面中 ...

  9. mysql数据存储方式_数据存储在mysql的两种方式

    数据存储在mysql的两种方式 发布时间:2020-05-12 16:16:25 来源:亿速云 阅读:250 作者:三月 下文主要给大家带来数据存储在mysql的两种方式,希望这些内容能够带给大家实际 ...

最新文章

  1. 基于深度学习的物体抓取位置估计
  2. 学习笔记---取得枚举项的2种方法: Enum.GetValues()-Array.GetValue()和Enum.GetNames()-Enum.Parse()...
  3. C六:指针可以比较大小
  4. POJ3694 Network
  5. username is marked non-null but is null
  6. 能被计算机硬件理解的语言,(计算机原理综合练习一含答案.doc
  7. asp.net中前台javascript与c#函数相互调方法
  8. window系统在cmd窗口中直接使用sqlmap命令进行sql注入测试
  9. html5背景图片幻灯片切换,如何将一个PPT的背景设置成另一个PPT的背景?
  10. ssd测试软件寿命查看,铅锤哥:怎么看SSD还能用多久?固态硬盘寿命的检测方法...
  11. 苹果手机小圆点怎么设置?悬浮球设置,轻松学会
  12. sympy 求微分方程_Sympy常用函数总结
  13. 彻底卸载360画报(流氓屏保软件)---亲测有效
  14. VTK错误解决合集(持续更新中......)
  15. 哈尔滨理工大学matlab,微软用户-Matlab软件简介哈尔滨理工大学数学建模组ppt课件...
  16. 【OpenGL】二十一、OpenGL 矩阵压栈与出栈 ( 不同类型矩阵变换先后顺序 | 渲染前不设置单位阵 | 压栈出栈原理分析 | 代码示例 )
  17. mongo 登陆_MongoDB 账号密码登录
  18. 【FTP】Entering Extended Passive Mode
  19. 计算机老是跳出usb设备无法识别,电脑一直弹出无法识别的USB设备的解决办法
  20. 河南城建计算机学院的设备条件,河南城建学院仪器设备技术指标和功能要求

热门文章

  1. Python 之 运算符
  2. xsync 集群同步脚本介绍(拷贝文件不同的部分)
  3. 深入了解vue中slot和slot-scope
  4. 机器学习代码实战——SVM(支持向量机)(使用不同核函数)
  5. Python数据结构与算法笔记(六):数据结构——列表和栈
  6. 《人月神话》读书笔记2--空间技能
  7. 今天老师本来想讲另外一个题目, 但是由于大家不是很了解数组,因此写了一些数组让我们练习...
  8. iOS核心动画CALayer和UIView
  9. oc语言中的构造方法
  10. [DB2]DB2中的数值类型