C 自定義比較 仿函式 函式與過載操作符

2021-10-05 06:20:34 字數 3742 閱讀 9130

cpp 比 c 方便不少不光因為其支援物件導向支援class,同樣還因為其支援泛型程式設計,有方便的stl庫。泛型要比巨集強大的多,是一種設計更巧妙的編譯期動態機制,型別安全,使得一些通用演算法的封裝變得十分方便。模板操作的是型別,特化的時候編譯器會做型別推導,這是模板乙個核心特徵。

根據c++標準,當乙個模板不被用到時它就不應該被具體化。對於cpp編譯器是如何特化,編譯成最終**,用到了惰性求值模式匹配。這篇文章簡單介紹了這兩個原理:學習haskell。

對於實際的使用,記住下面兩點:

這裡主要說一下 c++ 標準庫,尤其是stl涉及比較操作時的常用比較器。這裡是stl源**。

傳入函式編譯器來做型別推導,進行模板特化。看sort函式的模板宣告:

// 可以看出,排序要求容器支援隨機訪問迭代器,類似於陣列的那種下標偏移訪問

// 這裡 _compare 是型別, __comp 是例項,呼叫 sort 需要傳入的就是 __comp 例項

template

inline

void sort(_randomaccessiter __first, _randomaccessiter __last,

_compare __comp)

乙個例子如下:

typedef

struct tagnode node;

bool comp(const node &a, const node &b)

int main()

, , , , };

// 編譯器會進行型別推導做模板特化

sort(a, a + 5, comp);

return

0;}

仿函式functor的英文解釋為something that performs a function,即其行為類似函式的東西。c++中的仿函式是通過在類中過載()運算子實現,使你可以像使用函式一樣來建立類的物件。要求傳入仿函式的地方也很好理解,一般c++模板,尖括號<>裡面放的是型別,自然這需要比較器的時候傳入的也是比較器的型別,這就是用到仿函式的地方。

首先,看一下stl原始碼的模板宣告:

// map 和 set 底層儲存結構式都是紅黑樹

// forward declarations of operators == and <, needed for friend declarations.

template

class _compare __stl_dependent_default_tmpl(less<_key>),

class _alloc = __stl_default_allocator(_tp) >

class

map;

template

),class _alloc = __stl_default_allocator(_key) >

class

set;

// priority_queue 有優先順序,要求元素可比較。queue 和 priority_queue 預設的底層儲存結構也不同

// queue 預設用的是 deque 雙端佇列,priority_queue 用的是 vector

// priority_queue 實現使用的預設比較是 operator< ,是最大堆資料結構,即佇列頭元素值最大

template

class _sequence __stl_dependent_default_tmpl(deque

<_tp>) >

class

queue;

template

class _sequence __stl_dependent_default_tmpl(vector

<_tp>),

class _compare

__stl_dependent_default_tmpl(less)

class priority_queue; // 注意點:如果自己傳入自己的仿函式比較,那麼第二個儲存型別也要傳入不能預設

對於priority_queue用法,這篇文章裡的例子很不錯stl裡的priority_queue用法。

乙個注意點就是:如果使用自定義比較,使用仿函式,那麼使用時必然也要傳入第二個模板型別引數,要麼都預設,要麼都傳入。下面給乙個例子:

#include 

#include

using

namespace

std;

typedef

struct tagnode

node;

/* 針對某種型別的自定義比較仿函式,cpp 中 struct 相當於全部 public 的 class */

struct classcomp

};int main()

, , , , };

// classcomp 必須是針對 node 型別的比較仿函式,第二個預設儲存結構也不能少

priority_queuevector

, classcomp> prique;

for(unsigned

int i = 0; i < sizeof(a)/sizeof(a[0]); ++i)

while(!prique.empty())

return

0;}

過載<運算子,這種方式通用性會比較強,這種方式使得複雜結構變得像基本資料型別一樣可比較了。這樣就不用傳比較器了,因為預設的比較器這時已經生效了。對於 cpp **,過載運算子不管對於 struct 還是 class 都是很方便的,都是在自己定義的結構體或類型別裡加乙個過載的函式即可。這種方法缺點也是比較明顯的,如果有兩個模板容器對同一自定義資料結構(結構體或者類)需要不同的比較器,那麼過載<這種方法就沒有上面的自定義比較器(比較函式或者仿函式)適用了。

同樣給個例子:

#include 

#include

using

namespace

std;

// 過載運算子 讓cpp**的表達力有很大提公升,比如map過載可以翻遍用獲取指定key的value

// 還有如果定義了一些矩陣運算什麼的,過載 * 就更加方便靈活了

struct node

};int main()

, , , , };

priority_queueprique; //node 型別過載了 < ,變得像 int 等基本資料型別一樣可比較了

for(unsigned

int i = 0; i < sizeof(a)/sizeof(a[0]); ++i)

while(!prique.empty())

return

0;}

對於 cpp 中需要自定義比較時,如果以後的操作比較都是定的,可以用過載,否則還是用自定義比較函式和仿函式。還有就是stl中優先順序佇列priority_queue, 自定義仿函式是模板的第三個型別,如果自定了那麼第二個模板引數也要傳入,一般用vector就可以。

c++ 自定義比較:仿函式、函式與過載操作符

map自定義比較函式

from template class alloc alloc 第乙個引數key是關鍵字型別 第二個引數t是值型別 第三個引數compare是比較函式 仿函式 第四個引數是記憶體配置物件 map中的關鍵字,起碼必須有 這個比較操作符。我們知道,int,float,enum,size t等等簡單關鍵字...

自定義比較函式mystrcmp

實現乙個兩字串比較的函式 mystrcmp 不允許呼叫標準庫中的字串處理函式。當兩字串相等時,該函式返回 0 當第乙個字串大於第二字串時,該函式返回 1 當第乙個字串小於第二字串時,該函式返回 1。輸入格式 兩行,每行乙個字串,每個字串的長度不超過30。輸出格式 根據兩字串的大小,對應輸出 0,1,...

自定義lower bound比較函式

過載比較符號或者自定義比較函式均可。記得比較的時候需要放結構體進去比較。如用vetor存結構體比較或者直接結構體比較。include include include include include include include include include include include inc...