1. 程式人生 > >跟Google學寫程式碼--Chromium/base--stl_util原始碼學習及應用

跟Google學寫程式碼--Chromium/base--stl_util原始碼學習及應用

Ttile: 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); }

2 釋放容器內的指標物件
這裡隱藏了一個巨大的坑兒,就是迭代器的失效問題,之前也有部落格裡面介紹過:

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}
true

Test STLSetDifference {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:
6

Test STLSetIntersection {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:
1 2 3 4
Test STLIncludes {1, 2, 3, 4, 6} and { 1, 2, 3 ,4}:
true

Test STLClearObject:
vector size:0
vector capacity:0