罗剑锋的C++实战笔记15-三分天下的容器:恰当选择,事半功倍

今天我要讲的是标准库里的一块“重地”:容器,它也是 C++ 泛型编程范式的基础。

不过在正式开讲之前,我先问你个问题:什么是容器?

你也许会说:容器,就是能够“容纳”“存放”元素的一些数据结构。

这个回答非常正确,而且说到了“点”上。

还记得计算机先驱的那句经典名言吗?“算法 + 数据结构 = 程序。”在 C++ 里,容器就是这个公式里面的“数据结构”。

所以,下面我就着重从数据结构的角度,来谈谈各种容器的区别、优缺点,还有如何选择最合适的容器。

认识容器

所谓的数据结构,就是数据在计算机里的存储和组织形式,比如堆、数组、链表、二叉树、B+ 树、哈希表,等等。

在计算机的发展历史上,众多“大牛”孜孜不倦地发明创造了这么多的数据结构,为什么呢?

因为没有一种数据结构是万能的、可以应用于任何场景。毕竟,不同的数据结构存储数据的形式不一样,效率也就不一样。有的是连续存放,有的是分散存放,有的存储效率高,有的查找效率高,我们必须要依据具体的应用场合来进行取舍。

我想,你肯定已经学过这些数据结构了,也知道它们的实现原理,自己写也不是什么太难的事情。

但是,对于最基本、最经典的那些数据结构,你完全没有必要去“自己造轮子”,因为 C++ 标准库里的容器就已经把它们给实现了。

容器,其实就是 C++ 对数据结构的抽象和封装。而且,因为标准库开发者的功力很深,对编译器的了解程度更是远超你我,所以,容器的性能和优化水平要比我们自己写的好上几十倍,这一点你绝对不用质疑。

我们要做的,就是仔细品鉴标准容器这盘大餐,从中找出最合适自己口味的那道菜。

由于容器相关的资料已经有很多了,无论是看图书还是网站,都可以找到非常详细的接口文档,所以今天,我就不去罗列每个容器的具体操作方法了,而是把重点放在特性介绍上。掌握了这些特性,今后你在面临选择的时候,不用太纠结,就可以选出最适合你的容器。

容器的通用特性

你必须要知道所有容器都具有的一个基本特性:它保存元素采用的是“值”(value)语义,也就是说,容器里存储的是元素的拷贝、副本,而不是引用。

从这个基本特性可以得出一个推论,容器操作元素的很大一块成本就是值的拷贝。所以,如果元素比较大,或者非常多,那么操作时的拷贝开销就会很高,性能也就不会太好。

一个解决办法是,尽量为元素实现转移构造和转移赋值函数,在加入容器的时候使用 std::move() 来“转移”,减少元素复制的成本:

Point p; // 一个拷贝成本很高的对象

v.push_back(p); // 存储对象,拷贝构造,成本很高

v.push_back(std::move(p)); // 定义转移构造后就可以转移存储,降低成本

你也可以使用 C++11 为容器新增加的 emplace 操作函数,它可以“就地”构造元素,免去了构造后再拷贝、转移的成本,不但高效,而且用起来也很方便:

v.emplace_back(...); // 直接在容器里构造元素,不需要拷贝或者转移

当然,你可能还会想到在容器里存放元素的指针,来间接保存元素,但我不建议采用这种方案。

  • 27
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

程序员zhi路

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值