专栏首页程序员的酒和故事跟Google学写代码--Chromium/base--stl_util源码学习及应用

跟Google学写代码--Chromium/base--stl_util源码学习及应用

Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。

今天与大家分享的就是Chromium下base中的stl_util,是对stl的补充,封装,更有利于我们的使用,完全可以移植到自己的C++工程项目中来。

1 释放STL内存 Clears internal memory of an STL object.

我们知道,vector的clear()方法式清除了vector中的内容,但是vector object所占的内存不会清除。

因此,std_util中有个这个方法:

template<class T>void STLClearObject(T* obj) {
  T tmp;
  tmp.swap(*obj);  // Sometimes "T tmp" allocates objects with memory (arena implementation?).  // Hence using additional reserve(0) even if it doesn't always work.
  obj->reserve(0);
}

也就是使用swap,之前写过一篇博客: 《实战c++中的vector系列–正确释放vector的内存(clear(), swap(), shrink_to_fit())》 地址:http://blog.csdn.net/wangshubo1989/article/details/50359750

2 释放容器内的指针对象 这里隐藏了一个巨大的坑儿,就是迭代器的失效问题,之前也有博客里面介绍过:

《实战c++中的vector系列–可怕的迭代器失效(vector重新申请内存)》 地址:http://blog.csdn.net/wangshubo1989/article/details/50334297

《实战c++中的vector系列–可怕的迭代器失效之二(删除vector中元素)》 地址:http://blog.csdn.net/wangshubo1989/article/details/50334503

template <class ForwardIterator>void STLDeleteContainerPointers(ForwardIterator begin, ForwardIterator end) {  while (begin != end) {
    ForwardIterator temp = begin;
    ++begin;    delete *temp;
  }
}

3 正确删除容器内pairs对象

template <class ForwardIterator>void STLDeleteContainerPairPointers(ForwardIterator begin,
                                    ForwardIterator end) {  while (begin != end) {
    ForwardIterator temp = begin;
    ++begin;    delete temp->first;    delete temp->second;
  }
}

4 删除容器内pairs对象中的第一个元素

template <class ForwardIterator>void STLDeleteContainerPairFirstPointers(ForwardIterator begin,
                                         ForwardIterator end) {  while (begin != end) {
    ForwardIterator temp = begin;
    ++begin;    delete temp->first;
  }
}

5 删除容器内pairs对象中的第二个元素

template <class ForwardIterator>void STLDeleteContainerPairSecondPointers(ForwardIterator begin,
                                          ForwardIterator end) {  while (begin != end) {
    ForwardIterator temp = begin;
    ++begin;    delete temp->second;
  }
}

6 vector转为数组 一定要注意,vector可能为空的情况下。

template<typename T>inline T* vector_as_array(std::vector<T>* v) {  return v->empty() ? NULL : &*v->begin();
}
template<typename T>inline const T* vector_as_array(const std::vector<T>* v) {  return v->empty() ? NULL : &*v->begin();
}

7 string转为数组 还是是要注意string为空。

inline char* string_as_array(std::string* str) {  // DO NOT USE const_cast<char*>(str->data())
  return str->empty() ? NULL : &*str->begin();
}

8 查找关联容器中是否有某个特定的key 没什么好说的,提高效率,函数的参数为const引用类型。

template <typename Collection, typename Key>bool ContainsKey(const Collection& collection, const Key& key) {  return collection.find(key) != collection.end();
}

9 判断容器是否有序 这里用到了adjacent_find,在一个数组中寻找两个相邻的元素;

template <typename Container>bool STLIsSorted(const Container& cont) {  // Note: Use reverse iterator on container to ensure we only require
  // value_type to implement operator<.
  return std::adjacent_find(cont.rbegin(), cont.rend(),                            std::less<typename Container::value_type>())
      == cont.rend();
}

10 获得两个有序容器的不同 这里用到了DCHECK,是自己定义的宏:

#define DCHECK(condition)                                               \
  LAZY_STREAM(LOG_STREAM(DCHECK), DCHECK_IS_ON ? !(condition) : false)  \
  << "Check failed: " #condition ". "
template <typename ResultType, typename Arg1, typename Arg2>
ResultType STLSetDifference(const Arg1& a1, const Arg2& a2) {
  DCHECK(STLIsSorted(a1));
  DCHECK(STLIsSorted(a2));
  ResultType difference;  std::set_difference(a1.begin(), a1.end(),
                      a2.begin(), a2.end(),                      std::inserter(difference, difference.end()));  return difference;
}

11 合并两个有序的容器

template <typename ResultType, typename Arg1, typename Arg2>
ResultType STLSetUnion(const Arg1& a1, const Arg2& a2) {
  DCHECK(STLIsSorted(a1));
  DCHECK(STLIsSorted(a2));
  ResultType result;  std::set_union(a1.begin(), a1.end(),
                 a2.begin(), a2.end(),                 std::inserter(result, result.end()));  return result;
}

12 同时包含在两个容器中的元素 set_intersection:同时包含第一个和第二个集合中的元素

template <typename ResultType, typename Arg1, typename Arg2>
ResultType STLSetIntersection(const Arg1& a1, const Arg2& a2) {
  DCHECK(STLIsSorted(a1));
  DCHECK(STLIsSorted(a2));
  ResultType result;  std::set_intersection(a1.begin(), a1.end(),
                        a2.begin(), a2.end(),                        std::inserter(result, result.end()));  return result;
}

13 判断一个容器是否包含另一个容器的所有内容

template <typename Arg1, typename Arg2>bool STLIncludes(const Arg1& a1, const Arg2& a2) {
  DCHECK(STLIsSorted(a1));
  DCHECK(STLIsSorted(a2));  return std::includes(a1.begin(), a1.end(),
                       a2.begin(), a2.end());
}

应用: 对上面介绍的方法进行简单的使用,看看吧:

#include<iostream>#include<vector>#include<algorithm>#include"stl_util.h"int main()
{  std::vector<int> numbers{1, 2, 3, 4, 6};  std::vector<int> numbers1{ 1, 2, 3 ,4};  std::cout << "Test STLIsSorted:{1, 2, 3, 4, 6}" << std::endl;  std::cout << std::boolalpha <<STLIsSorted(numbers) << std::endl << std::endl;  std::cout << "Test STLSetDifference {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:" << std::endl;  std::vector<int> difference_result;
  difference_result = STLSetDifference<std::vector<int>, std::vector<int>, std::vector<int>>(numbers, numbers1);  for(auto iter: difference_result)
  {    std::cout << iter << std::endl << std::endl;
  }  std::cout << "Test STLSetIntersection {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:" << std::endl;  std::vector<int> intersection_result;
  intersection_result = STLSetIntersection<std::vector<int>, std::vector<int>, std::vector<int>>(numbers, numbers1);  for (auto iter : intersection_result)
  {    std::cout << iter << " " ;
  }  std::cout << std::endl;  std::cout << "Test STLIncludes {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:" << std::endl;  std::cout << std::boolalpha << STLIncludes(numbers, numbers1) << std::endl << std::endl;  std::cout << "Test STLClearObject:" << std::endl;
  STLClearObject(&numbers);  std::cout << "vector size:" << numbers.size() << std::endl;  std::cout << "vector capacity:" << numbers.capacity() << std::endl << std::endl;

  system("pause");  return 0;
}

输出结果:

Test STLIsSorted:{1, 2, 3, 4, 6}trueTest STLSetDifference {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:6Test STLSetIntersection {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:1 2 3 4Test STLIncludes {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:trueTest STLClearObject:vector size:0vector capacity:0

本文分享自微信公众号 - 程序员的酒和故事(cppdabaojian),作者:wangshubo1989

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-01-16

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • libphonenumber--windows上编译libphonenumber.lib以及使用(C++、VS2015)

    再介绍一个谷歌的,自带光环的库–libphonenumber. 虽然这个库是用c++写的,但是我们在网络上很少见到在C++开发中使用这个库,或是说在window...

    程序员的酒和故事
  • 为什么C++不会衰老

    Thoughts about C++ in the modern world. 一些关于当代C++的思考。 ? Debates about the pre...

    程序员的酒和故事
  • 跟Google学写代码--Chromium/base--windows_version源码学习及应用

    Chromium是一个伟大的、庞大的开源工程,很多值得我们学习的地方。 前面写道: 《跟Google学写代码–Chromium/base–stl_util源...

    程序员的酒和故事
  • 运行时类型识别

    运行时类型识别(run-time type identification, RTTI)的功能由两个运算符实现:

    Rock_Lee
  • 实战贴:开源GUI LittlevGL在MCU上的移植

    前几天看见正点原子发布了LittlevGL的教程,这个GUI貌似又火了,于是应读者要求,我也来移植一下,将正点原子的这个GUI移植到小熊派上,不到一会功夫就搞定...

    morixinguan
  • C++ std::vector元素的内存分配问题(补充)

    在上篇博文C++ std::vector元素的内存分配问题中我们已经明确了使用std::vector容器时元素在内存中的创建情况。 所以,我个人觉得使用st...

    卡尔曼和玻尔兹曼谁曼
  • 【开发指南】(二)Ionic3开发工具插件推荐

    ionic主要使用网页的开发方式,一般的web开发的IDE就可以了,有大型的也有轻量级的供考虑,每个开发人员都有自身喜爱和倾向的IDE,在此不一一列举了,个人推...

    IT晴天
  • curl 命令操作 Kubernetes API

    Kubernetes API是集群系统中的重要组成部分,Kubernetes中各种资源(对象)的数据通过该API接口被提交到后端的持久化存储(etcd)中,Ku...

    我的小碗汤
  • 机器学习之决策树(下)

    这就是所谓的过拟合,当深度越深,分的次数越多,训练集的错误率还ok,但是在测试集就完了。

    润森
  • JavaScript 编程精解 中文第三版 五、高阶函数

    ApacheCN_飞龙

扫码关注云+社区

领取腾讯云代金券