惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

MyScale Blog
MyScale Blog
爱范儿
爱范儿
The Register - Security
The Register - Security
小众软件
小众软件
D
DataBreaches.Net
雷峰网
雷峰网
S
Secure Thoughts
L
LINUX DO - 最新话题
M
MIT News - Artificial intelligence
Application and Cybersecurity Blog
Application and Cybersecurity Blog
罗磊的独立博客
F
Fortinet All Blogs
博客园 - 叶小钗
TaoSecurity Blog
TaoSecurity Blog
博客园 - Franky
aimingoo的专栏
aimingoo的专栏
S
SegmentFault 最新的问题
Hacker News: Ask HN
Hacker News: Ask HN
Help Net Security
Help Net Security
N
News and Events Feed by Topic
S
Security Affairs
The Last Watchdog
The Last Watchdog
Forbes - Security
Forbes - Security
S
Security @ Cisco Blogs
Latest news
Latest news
O
OpenAI News
N
Netflix TechBlog - Medium
云风的 BLOG
云风的 BLOG
Blog — PlanetScale
Blog — PlanetScale
Google Online Security Blog
Google Online Security Blog
S
Securelist
博客园 - 司徒正美
Exploit-DB.com RSS Feed
Exploit-DB.com RSS Feed
P
Proofpoint News Feed
T
Threat Research - Cisco Blogs
C
CXSECURITY Database RSS Feed - CXSecurity.com
P
Palo Alto Networks Blog
T
The Blog of Author Tim Ferriss
Stack Overflow Blog
Stack Overflow Blog
I
InfoQ
阮一峰的网络日志
阮一峰的网络日志
AI
AI
SecWiki News
SecWiki News
G
GRAHAM CLULEY
Cloudbric
Cloudbric
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
L
LINUX DO - 热门话题
C
Cybersecurity and Infrastructure Security Agency CISA
B
Blog RSS Feed

博客园 - SweetDream

如何使用SecureCRT连接ubuntu (转) 转 linux共享 VC++中的char,wchar_t,TCHAR(转载) 【转】Linux内核学习笔记(5)连载---实模式、保护模式和虚拟8086方式 concept 计算机英语 C++备忘录(记录一些不常使用的语法规则) VS2005 快捷键 网摘 君心莫邪 迭代器(iterators) 空间配置器(allocator) 函数返回引用或指针的选择 【转】最节省时间的方法——学习 C++数据类型速查 Cegui的事件机制 C++不定参数 Lua 与 C 交互(2) Lua 与 C 交互(1)
Effective STL 笔记 <容器>
SweetDream · 2008-12-02 · via 博客园 - SweetDream

1.容器无关代码不存在,也就是不存在一种万能的容器,任何容器都有它存在的价值和用武之地.

2.因为容器类型可能会改变所以不要这么写:

class Widget {...};

vector<Widget> vw;

// ...

Widget bestWidget;

vector<Widget>::iterator i = find(vw.begin(), vw.end(), bestWidget);

而是这么写:

class Widget { ... };

typedef vector<Widget> WidgetContainer;

typedef WidgetContainer::iterator WCIterator;

WidgetContainer cw;

// ...

Widget bestWidget;

WCIterator i = find(cw.begin(), cw.end(), bestWidget);

3.如果你需要建立一个客户列表,请不要直接用list。取而代之的是,建立一个CustomerList类,把list隐藏在它的private区域:

class CustomerList

{

private:

     typedef std::list<Customer> CustomerContainer;

     typedef CustomerContainer::iterator CCIterator;

     CustomerContainer customers;

public:         // 通过这个接口

     ...         // 限制list特殊信息的可见性

};

4.用empty来代替检查size()是否为0

if (c.size() == 0)... 写为if (c.empty())...

于所有的标准容器,empty是一个常数时间的操作,但对于一些list实现,size花费线性时间, sizesplice的区间形式——必须让步。即如果要保持一个size的常数,就要在splice的时候遍历一般获得新的size,或者保持splice是常数,就要保证获得listsize要遍历一遍数据,也就是一个或者另一个可以是常数时间操作,但不能都是。

5. 尽量使用区间成员函数代替它们的单元素兄弟,区间成员函数是一个像STL算法的成员函数,使用两个迭代器参数来指定元素的一个区间来进行某个操作,它通常比单元素操作要直观和高效。

区间构造:

所有标准容器都提供这种形式的构造函数:

container::container(InputIterator begin,      // 区间的起点

                        InputIterator end);   // 区间的终点

区间插入:

所有标准序列容器都提供这种形式的insert

void container::insert(iterator position,      // 区间插入的位置

                          InputIterator begin, // 插入区间的起点

                          InputIterator end); // 插入区间的终点

关联容器使用它们的比较函数来决定元素要放在哪里,所以它们了省略position参数:

void container::insert(lnputIterator begin, InputIterator end);

区间删除。

每个标准容器都提供了一个区间形式的erase,但是序列和关联容器的返回类型不同。

序列容器提供了这个:

iterator container::erase(iterator begin, iterator end);

关联容器提供这个:

void container::erase(iterator begin, iterator end);

区间赋值:

所有标准序列容器都提供了区间形式的assign

void container::assign(InputIterator begin, InputIterator end);

 6.删除元素

全局的remove算法:

template <class ForwardIterator, class T>

ForwardIterator remove(ForwardIterator first, ForwardIterator last,

                          const T& value);

这个算法会把[first,last)中不等于value的元素放到这段区域的最前面,但是不会改变容器的size,也就是后面会余下一定数目(value相等元素的个数)的无效区域,并返回这个无效区域的first。为啥要这样,而不是把这些元素直接从容器中删除呢?

1.全局算法(非容器成员函数)不知道容器一些属性,比如容器的end,这个函数中的firstlast不一定是容器的firstend,因此它也没权利去移动容器的后续元素去弥补这个无效区域。

因此对于vectordequestring删除元素的最好方法是erase-remove惯用法:

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

c.erase(remove_if(c.begin(), c.end(), badValue), c.end());

对于list也可以这么做,但是list的成员函数remove更高效:

c.remove(nValue);

c.remove_if(badValue);

对于关联容器(setmultisetmapmultimap)应该是调用erase

c.erase(nValue);

对于需要条件badValue的情况,需要遍历关联容器,然后一个一个删除。

遍历删除需要注意的:

A.如果容器是标准序列容器,写一个循环来遍历容器元素,每当调用erase时记得都用它的返回值更新你的迭代器。因为对于序列容器erase不仅使所有指向被删元素的迭代器失效,也使被删元素之后的所有迭代器失效。

         SeqContainer<int> c;

// ...

for (SeqContainer<int>::iterator i = c.begin(); i != c.end();)

{

          if (badValue(*i))

          {

               logFile << "Erasing " << *i << '\n';

// 标准序列容器erase返回被删元素之后的元素的有效迭代器。

               i = c.erase(i);  

          }

          else

          {

               ++i;

          }

}

B.如果容器是标准关联容器,写一个循环来遍历容器元素,当你把迭代器传给erase时记得后置递增它。

AssocContainer<int> c;

// ...

for (AssocContainer<int>::iterator i = c.begin(); i != c.end();)

{

          if (badValue(*i))

          {

// 标准关联容器的erase的返回类型是void

               c.erase(i++);

          }

          else

          {

               ++i;

          }

}

7. 使用交换技巧来修整过剩容量

vector<Contestant>(contestants).swap(contestants);

contestant.swap的作用和swap(constestantsA, constestantsB)是一样的。用于交换2个容器的内容。

template <class Assignable>

void swap(Assignable& a, Assignable& b);

8.避免使用vector<bool>

很多STL的实现对于vector<bool>并不保存真正的bool,而是打包bool以节省空间。在一个典型的实现中,每个保存在“vector”中的“bool”占用一个单独的比特,而一个8比特的字节将容纳8“bool”这将使很多操作比较危险。

2个办法可以解决这个问题:

1.           deque<bool>deque提供了几乎所有vector所提供的(唯一值得注意的是reservecapacity),而deque<bool>是一个STL容器,它保存真正的bool值。

2.    使用bitset