boolan c++ stl 第四周筆記

weixin_34253539發表於2017-12-14

Algorithm

clipboard.png

迭代器分類

clipboard.png

迭代器型別對演算法的影響

clipboard.png

clipboard.png

clipboard.png

仿函式

  • STL各部分關係

clipboard.png

容器通過記憶體分配器分配空間;容器和演算法因為迭代器而分離,演算法通過迭代器訪問容器;仿函式協助演算法指定不同的策略;介面卡套接仿函式。仿函式將某種"行為"作為演算法的引數傳給演算法。

仿函式介面卡(Function Adapter)

  • binder1st

給定一個vector,其元素為:[0,0,0,1,0],想要匹配到第一個非零元素。我們有find_if()的演算法和not_equal_to的函式物件,根據這兩個東西就可以實現我們的目的。然而,not_equal_to()(const T& a,const T&b),並不能接受一個引數;find_if()又是向最後一個函式物件直接給予一個引用作為引數,所以無法編譯通過。為此使用binder1st來把其中的一個引數固定下來。

vector<int>::iterator it = find_if(v.begin(),v.end(),bind1st(not_equal_to<int>(),0));
  • binder2nd

clipboard.png

  • 為了這種機制的考慮,在所有的仿函式中都要有first_argument_type等這幾個typedef。通常通過派生自binary_function<class Arg1,class Arg2,class Result>可以直接得到。
  • 例如 binder1st<not_equal_to<int>>(f,0)就代表生成一個函式物件func(x)=f(0,x);
  • 各種函式介面卡都是以例項化後的仿函式的型別作為模板引數的類别範本,這是函式介面卡的重要標誌。

迭代器介面卡

  • reverse_iterator

clipboard.png

一些注意點

  1. 注意如果使用了諸如push(new Point(x,y))這種語法,必須要在刪除容器之前遍歷容器進行記憶體釋放,否則就發生了記憶體洩露。
  2. 儘量用演算法代替手寫的迴圈,一方面是從效率的角度考慮,另一方面使用演算法的這種方式更好地體現了物件導向的思想。
  3. 容器的size和capacity

Capacity是容器"佔據"的空間,size是容器"使用"的空間。所以容器有可能佔據了很大的空間然而並沒有使用那一部分空間,那麼這種情況下應該通過swap方法對容器進行縮小。

  1. 為什麼建議在容器中放指標而不是物件?

1.拷貝的開銷比較大。
2.如果存在繼承,就會發生slicing。即由於儲存的僅僅是基類物件,其留下的大小也就是基類物件的大小。如果存在繼承關係時,若將派生類物件放入容器,則只會保留基類部分,派生類部分會丟失。這種方式體現出了C++中的多型性。

一些泛型演算法

  • for_each
template<class _InIt,class _Fnl> inline

_Fnl for_each(_InIt _First, _InIt _Last, _Fnl _Func)

for_each就是把兩個迭代器之間的物件例項扔給_Func作為唯一引數。注意,_Func不一定非得是函式物件(仿函式),直接傳函式名或函式指標也是可以的。

  • find
template<class _InIt,class _Ty> inline

_Ty find(_InIt _First, _InIt _Last,const _Ty& _Val)

如果在左閉右開區間內找到了值為_Val的物件則返回該迭代器,否則返回器尾部迭代器。

  • find_if
template<class _InIt,class _Pr> inline

_Ty find(_InIt _First, _InIt _Last,const _Pr _Pred)

_Pr為一個函式名或者函式物件(仿函式)。如果在左閉右開區間內找到了的能使得這一物件返回真的,則返回該迭代器,否則返回器尾部迭代器。注意_Pr為單參,注意聯合介面卡的使用。

  • adjacent_find

    template <class ForwardIterator>
    
    ForwardIterator adjacent_find (ForwardIterator first, ForwardIterator last);
    

返回第一個遇到的兩個連續相等的物件中,第一個物件的迭代器,如對於[0,1,2,3,3,4],則返回指向第一個3的迭代器。

template<class _InIt,class _Pr> inline

_Ty find(_InIt _First, _InIt _Last,const _Pr _Pred)

Adjacent的操作實際上是針對自己和後繼進行的比較操作。除了預設的等於比較操作之外,也可以使用自定義的函式或仿函式。_Pred 具有兩個引數,使用時會把連續的兩個值分別作為第一引數和第二引數求真值。

  • find_first_of
template <class ForwardIterator1, class ForwardIterator2>

ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1,

ForwardIterator2 first2, ForwardIterator2 last2);

 

template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>

ForwardIterator1 find_first_of (ForwardIterator1 first1, ForwardIterator1 last1,

ForwardIterator2 first2, ForwardIterator2 last2,

BinaryPredicate pred);

它是在兩組區間內搜尋是否有it1==it2,如果有就返回第一組區間內物件的迭代器。也可以使用自定義的雙參函式進行比較。

  • count/count_if
template <class InputIterator, class T>

typename iterator_traits<InputIterator>::difference_type

count (InputIterator first, InputIterator last, const T& val);

返回左閉右開區間中值等於val的元素的個數。

類比find,count_if就是自己指定所想使用的函式。同樣地,其為單參,要注意兩對介面卡的使用。

  • mismatch
template <class InputIterator1, class InputIterator2, class BinaryPredicate>

pair<InputIterator1, InputIterator2>

mismatch (InputIterator1 first1, InputIterator1 last1,

InputIterator2 first2, BinaryPredicate pred);

當不指定最後一個函式時,其作用是逐元素比對兩個序列,返回指向第一個容器中的第一個不一致的迭代器。如果指定函式,則是需要返回值等於False。

  • equal
template <class InputIterator1, class InputIterator2, class BinaryPredicate>

bool equal (InputIterator1 first1, InputIterator1 last1,

InputIterator2 first2, BinaryPredicate pred);

當不指定最後一個函式時,其作用是檢查兩個容器內容是否完全相等。若指定最後一個函式,則是逐元素檢查是否滿足兩兩返回值均為True。

  • search
template <class ForwardIterator1, class ForwardIterator2, class BinaryPredicate>

ForwardIterator1 search (ForwardIterator1 first1, ForwardIterator1 last1,

ForwardIterator2 first2, ForwardIterator2 last2,

BinaryPredicate pred);

當不指定最後一個函式時,其作用是搜尋前一個序列中是否存在和第二個序列相同的子序列;如果自定義判別函式,則是逐元素比對,搜尋是否存在能夠和第二個序列匹配的序列。返回值為第一個序列中匹配的位置,如果找不到則返回末位迭代器。

相關文章