跟Google學寫程式碼--Chromium/base--stl_util原始碼學習及應用
阿新 • • 發佈:2019-02-19
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