C++容器使用经验总结(一)

本文涉及的产品
容器镜像服务 ACR,镜像仓库100个 不限时长
简介: 容器 第1条:慎重选择容器类型。 标准STL序列容器:vector、string、deque和list。 标准STL关联容器:set、multiset、map和multimap。 非标准序列容器slist和rope。slist是一个单向链表,rope本质上是一“重型”string。 非标准的关联容器hash_set、hase_multiset、hash_map和hash_mu

容器

1条:慎重选择容器类型。

标准STL序列容器:vectorstringdequelist

标准STL关联容器:setmultisetmapmultimap

非标准序列容器slistropeslist是一个单向链表,rope本质上是一“重型”string

非标准的关联容器hash_sethase_multisethash_maphash_multimap

vector<char> 作为string的替代。(见第13)

vector作为标准关联容器的替代。(见第23)

几种标准的非STL容器,包括数组、bitsetvalarraystackqueuepriority_queue

你是否关心容器中的元素是如何排序的?如果不关心,选择哈希容器.

容器中数据的布局是否需要和C兼容?如果需要兼容,就只能选择vector(见第16)

元素的查找速度是否是关键的考虑因素?如果是,就要考虑哈希容器、排序的vector和标准关联容器-或许这就是优先顺序。

对插入和删除操作,你需要事务语义吗?如果是,只能选择list。因为在标准容器中,只有list对多个元素的插入操作提供了事务语义。

deque是唯一的、迭代器可能会变为无效(插入操作仅在容器末尾发生时,deque的迭代器可能会变为无效)而指向数据的指针和引用依然有效的标准STL容器。

2条:不要试图编写独立于容器类型的代码。

如果你想编写对大多数的容器都适用的代码,你只能使用它们的功能的交集。不同的容器是不同的,它们有非常明显的优缺点。它们并不是被设计用来交换使用的。

  你无法编写独立于容器的代码,但是,它们(指客户代码)可能可以。

3条:确保容器中的对象拷贝正确而高效。

copy in,copy out,是STL的工作方式,它总的设计思想是为了避免不必要的拷贝。使拷贝动作高效并且防止剥离问题发生的一个简单办法是使容器包含指针而不是对象。

4条:调用empty而不是检查size()是否为0

  理由很简单:empty对所有的标准容器都是常数时间操作,而对一些list的实现,size耗费线性时间。

5条:区间成员函数优先于与之对应的单元素成员函数。

区间成员函数写起来更容易,更能清楚地表达你的意图,而且它们表现出了更高的效率。

6条:当心C++编译器最烦人的分析机制。

把形参加括号是合法的,把整个形参的声明(包括数据类型和形参名字)用括号括起来是非法的。

7条:如果容器中包含了通过new操作创建的指针,切记在容器对象析构前将指针delete掉。

STL很智能,但没有智能到知道是否该删除自己所包含的指针所指向的对象的程度。为了避免资源泄漏,你必须在容器被析构前手工删除其中的每个指针,或使用引用计数形式的智能指针(比如Boostsharedprt)代替指针。

8条:切勿创建包含auto_ptr的容器对象。

拷贝一个auto_ptr意味着改变它的值。例如对一个包含auto_ptrvector调用sort排序,结果是vector的几个元素被置为NULL而相应的元素被删除了。

9条:慎重选择删除元素的方法。

要删除容器中指定值的所有对象:

如果容器是vectorstringdeque,则使用erase-remove习惯用法。

SeqContainer<int> c;

c.erase(remove(c.begin(),c.end(),1963),c.end());

如果容器是list,则使用list::remove

如果容器是一个标准关联容器,则使用它的erase成员函数。

要删除容器中满足特定条件的所有对象:

如果容器是vectorstringdeque,则使用erase-remove_if习惯用法。

如果容器是list,则使用list::remove_if

如果容器是一个标准关联容器,则使用remove_copy_ifswap,或者写一个循环遍历容器的元素,记住当把迭代器传给erase时,要对它进行后缀递增。

AssocCOntainer<int> c;

...

AssocContainer<int> goodValues;

remove_copy_if(c.begin(), c.end(), inserter(goodValues, goodValues.end()),badValue);

c.swap(goodValues);

for(AssocContainer<int>::iterator i = c.begin();i !=c.end();/* do nothing */){

if(badValue(*i)) c.erase(i++);

else ++i;

}

要在循环内部做某些(除了删除对象之外的)操作:

如果容器是一个标准序列容器,则写一个循环来遍历容器中的元素,记住每次掉用erase时,要用它的返回值更新迭代器。

如果容器是一个标准关联容器,则写一个循环来遍历容器中的元素,记住每次把迭代器传给erase时,要对迭代器做后缀递增。

10条:了解分配子(allocator)的约定和限制。

11条:理解自定义分配子的合理用法。

12条:切勿对STL容器的线程安全性有不切实际的依赖。

对一个STL实现你最多只能期望:

多个线程读是安全的。

多个线程对不同的容器写入操作是安全的。

你不能期望STL库会把你从手工同步控制中解脱出来,而且你不能依赖于任何线程支持。


目录
相关文章
|
22天前
|
设计模式 存储 Android开发
c++的学习之路:18、容器适配器与反向迭代器
c++的学习之路:18、容器适配器与反向迭代器
21 0
|
6天前
|
调度 C++ 容器
【C++】手搓 list 容器
本文我们实现了STL库中重要的list 的模拟实现,其中最重要莫过于迭代器的封装类的书写,这是前所未有的操作(对于我来说,我是第一次使用这种结构)。通过list 的模拟实现也帮我们巩固了类与对象的知识,也强化了指针操作的思路。欢迎大家讨论分析。
12 1
|
8天前
|
存储 设计模式 算法
【C++/STL】stack和queue(容器适配器、优先队列、双端队列)
【C++/STL】stack和queue(容器适配器、优先队列、双端队列)
13 1
|
14天前
|
存储 算法 C++
详解C++中的STL(标准模板库)容器
【4月更文挑战第30天】C++ STL容器包括序列容器(如`vector`、`list`、`deque`、`forward_list`、`array`和`string`)、关联容器(如`set`、`multiset`、`map`和`multimap`)和容器适配器(如`stack`、`queue`和`priority_queue`)。它们为动态数组、链表、栈、队列、集合和映射等数据结构提供了高效实现。选择合适的容器类型可优化性能,满足不同编程需求。
|
20天前
|
存储 算法 程序员
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
C++从入门到精通:2.2.1标准库与STL容器算法深度解析
|
28天前
|
C++ 容器
约瑟夫经典问题C++,STL容器queue解法
约瑟夫经典问题C++,STL容器queue解法
14 0
|
1月前
|
容器
C++map/multimap容器
C++map/multimap容器
|
1月前
|
C++ 容器
C++入门到理解set/multiset容器、pair对组
C++入门到理解set/multiset容器、pair对组
C++入门到理解set/multiset容器、pair对组
|
1月前
|
存储 C语言 C++
C++中STL常用容器(vector、deque、list、map、set)一文带你了解
C++中STL常用容器(vector、deque、list、map、set)一文带你了解
|
1月前
|
存储 算法 C++
C++容器STL相关面试问题
C++容器STL相关面试问题