#include <iostream> #include <algorithm> using namespace std; //回調函數 void call_back(char elem) { cout << elem << endl; } //仿函數 struct Functor { void operator() (char elem) { cout << elem << endl; } }; int main() { string strA = "hello"; string strB = "world"; for_each(strA.begin(),strA.end(),Functor()); cout<<"===========GAP==============="<<endl; for_each(strB.begin(),strB.end(),call_back); getchar(); return 0; }
h
e
l
l
o
===========GAP===============
w
o
r
l
dios
可能會有疑問二者有什麼區別?shell
假如我要for_each遍歷的不是字符串而是int類型的vector呢?函數
是否是又要重寫一個int類型做爲參數的回調函數,那若是有N種類型的容器遍歷豈不是要寫N個回調函數或N個仿函數類?this
非也!!!spa
C++有類模板 也有 函數模板 一樣能夠用於回調code
#include <iostream> #include <algorithm> #include <vector> using namespace std; //模板函數 template<typename T> void call_back(T elem) { cout<< elem <<endl; } //仿函數 template<typename T> class Functor { public: Functor() :m_val(0) { cout<< "Functor()" <<endl; } ~Functor() { cout<<"~Functor()"<<endl; } void operator() (T elem) { Do(elem); } //舉個栗子 void Do(T elem) { m_val+=elem; cout<<elem<<"/"<<m_val<<endl; } private: T m_val; }; int main() { vector<int> vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); for_each(vec.begin(),vec.end(),call_back<int>); cout<<"===========GAP==============="<<endl; for_each(vec.begin(),vec.end(),Functor<int>()); return 0; }
1
2
3
4
5
===========GAP===============
Functor()
1/1
2/3
3/6
4/10
5/15
~Functor()
~Functor()
~Functor()orm
三次析構的緣由:對象
先附上for_each的源碼(VC2008)繼承
template<class _InIt,class _Fn1> inline _Fn1 for_each(_InIt _First, _InIt _Last, _Fn1 _Func) { // perform function for each element _DEBUG_RANGE(_First, _Last); _DEBUG_POINTER(_Func); _CHECKED_BASE_TYPE(_InIt) _ChkFirst(_CHECKED_BASE(_First)); _CHECKED_BASE_TYPE(_InIt) _ChkLast(_CHECKED_BASE(_Last)); for (; _ChkFirst != _ChkLast; ++_ChkFirst) _Func(*_ChkFirst); return (_Func); }
Functor<int>() 產生臨時對象傳參(值) 構造一次,析構一次 for_each參數值傳遞,拷貝構造一次,析構一次(函數內部) for_each返回仿函數的對象(值),拷貝構造一次,析構一次 由於沒有重載拷貝構造函數 因此打印出第一次建立臨時對象時的普通構造函數 實際上在這個過程當中一共產生過三個仿函數對象
若是把代碼改變下:element
#include <iostream> #include <algorithm> #include <vector> using namespace std; template<typename T> class Functor { public: Functor() :m_val(0) { cout<< "Functor()"<<this<<endl; } Functor(Functor& that) { this->m_val = that.m_val; cout<< "Copy Functor()" <<this<<endl; } ~Functor() { cout<<"~Functor()"<<this<<endl; } void operator() (T elem) { Do(elem); } //舉個栗子 void Do(T elem) { m_val+=elem; cout<<elem<<"/"<<m_val<<endl; } T getVal() { return m_val; } private: T m_val; }; int main() { vector<int> vec; vec.push_back(1); vec.push_back(2); vec.push_back(3); vec.push_back(4); vec.push_back(5); Functor<int> func; Functor<int>& ref = for_each(vec.begin(),vec.end(),func); cout<<ref.getVal()<<endl; return 0; }
運行結果
Functor()0032F800 //main函數中的實參仿函數對象
Copy Functor()0032F68C //值傳遞 對【實參對象】拷貝構造了形參對象
1/1
2/3
3/6
4/10
5/15
Copy Functor()0032F7E8 //返回對象的值類型 對【形參對象】拷貝構造
~Functor()0032F68C //析構形參對象
15
~Functor()0032F7E8 //析構返回值對象
~Functor()0032F800 //析構實參對象
如今一目瞭然了吧!
我的認爲使用回調函數高效 由上面的例子能夠看出 構造1次 拷貝構造2次 析構3次 是有代價的
最後回到仿函數和回調函數
區別在於:
使用仿函數能夠聲明在業務相關的類內部 縮小做用域
使用仿函數能夠使用類的成員屬性和成員函數
仿函數是一個類 能夠使用面向對象的各類機制(封裝 繼承 多態)
若使用回調函數 那麼只能聲明爲某個類的靜態成員函數或全局函數,使用類內部的資源須要用一些手段傳參,沒有直接使用成員函數便捷