觀察這個結果,我們可以看到remove_if()實際上是根據條件對迭代地址進行了修改,在數據的後面存在一些殘余的數據,那些需要刪除的數據。剩下的數據的位置可能不是原來的數據,但他們是不知道的。
調用erase()來刪除那些殘余的數據。注意上面例子中通過erase()刪除remove_if()的結果和vs.enc()范圍的數據。
#####################
以前在使用stl的過程中發現bind1st和bind2nd這兩個函數,當時不太理解什麼意思,今天在網上查了一下相關資料發現竟然很簡單,下面我就具體解釋一下他們的用法。
bind1st和bind2nd函數用於將一個二元算子(binary functor,bf)轉換成一元算子(unary functor,uf)。為了達到這個目的,它們需要兩個參數:要轉換的bf和一個值(v)。
可能這麼解釋以後大家還不是很清楚,那麼就說點白話吧。我們在做比較的時候所寫的表達式像 x > k ,x < k,這裡的k是一個參數表示你程序裡面的表達式要和k值去比較。上面這兩個表達式對應的應該是bind2nd ,簡單的理解就是把k作為比較表達式的第二個參數。如果使用bind1st則對應的表達式是 k > x,k < x,也就是把k作為比較表達式的第一個參數。大家可能會注意到這裡面沒有=的比較,先別著急,後面將會說道如何實現=的比較。先舉兩個例子看看 bind1st和bind2nd的用法。
int a[] = {1, 2, 100, 200};
std::vector< int> arr(a, a + 4);
// 移除所有小於100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::bind2nd( std::less< int>(), 100)), arr.end());
這裡的比較表達式相當於arr.value < 100
如果用bind1st則表達的意思就恰恰相反
// 移除所有大於100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::bind1st( std::less< int>(), 100)), arr.end());
這裡的表達式相當於100 < arr.value
當然為了實現刪除大於100的元素你同樣可以使用bind2nd
// 移除所有大於100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::bind2nd( std::greater< int>(), 100)), arr.end());
前面說道=的比較,比如說x <= k怎麼實現呢,std又提供了一個好東西not1,我們可以說 !(x > k) 和 x <= k是等價的,那麼我們看看下面的表達式:
// 移除所有小於等於100的元素
arr.erase( std::remove_if( arr.begin(), arr.end(),
std::not1(std::bind2nd( std::greater< int>(), 100))), arr.end());
++++++++++++++
以前使用bind1st以及bind2nd很少,後來發現這兩個函數還挺好玩的,於是關心上了。
在C++ Primer對於bind函數的描述如下:
“
綁定器binder通過把二元函數對象的一個實參綁定到一個特殊的值上將其轉換成一元函數對象
C++標准庫提供了兩種預定義的binder 適配器bind1st 和bind2nd 正如你所預料的bind1st 把值綁定到二元函數對象的第一個實參上bind2nd 把值綁定在第二個實參上
例如
為了計數容器中所有小於或等於10 的元素的個數我們可以這樣向count_if()傳遞
count_if( vec.begin(), vec.end(), bind2nd( less_equal<int>(), 10 ));
”
哦,這倒是挺有意思的。於是依葫蘆畫瓢:
bool print(int i, int j)
{
std::cout<< i << "---" << j << std::endl;
return i>j;
}
int main(int argc, char *argv[])
{
(std::bind1st(print, 2))(1);
return 0;
}
滿懷希望它能夠打印
2---1
只不過。。。編譯出錯:
1 Error error C2784: 'std::binder1st<_Fn2> std::bind1st(const _Fn2 &,const _Ty &)' : could not deduce template argument for 'overloaded function type' from 'overloaded function type'
---不能夠推斷出模板參數for 'overloaded function type' from 'overloaded function type' 。。。。
(還真看不明白。。。)
於是直接看bind1st代碼:
template<class _Fn2,
class _Ty> inline
binder1st<_Fn2> bind1st(const _Fn2& _Func, const _Ty& _Left)
{
typename _Fn2::first_argument_type _Val(_Left);
return (std::binder1st<_Fn2>(_Func, _Val));
}
嗯。。。在代碼裡
typename _Fn2::first_argument_type _Val(_Left)
說必須定義first_argument_type類型,可是我一個函數,哪裡來的這個類型定義?嗯,STL一定提供了某種東東用來自動定義這個類型。找啊找,於是找到了ptr_fun。
這個函數自動將一個函數指針轉換為一個binary_function的繼承類pointer_to_binary_function,而在binary_function中定義了first_argument_type。
於是修改代碼:
int main(int argc, char *argv[])
{
(std::bind1st(std::ptr_fun(print), 2))(1);
return 0;
}
打印結果如下:
2---1
http://msdn.microsoft.com/en-us/library/506zz1f0%28VS.80%29.aspx
Standard C++ Library Reference
ptr_fun
Helper template functions used to convert unary and binary function pointers, respectively, into unary and binary adaptable functions.
template<class Arg, class Result> pointer_to_unary_function<Arg, Result, Result (*)(Arg)> ptr_fun(Result (*_pfunc)(Arg));template<class Arg1, class Arg2, class Result> pointer_to_binary_function<Arg1, Arg2, Result, Result (*)(Arg1, Arg2)> ptr_fun(Result (*_pfunc)(Arg1, Arg2));Parameters
_pfunc
The unary or binary function pointer to be converted to an adaptable function.
bind1st bind2nd的使用 || remove_if() - 飛不會 - 飛不會的博客 Return Value
The first template function returns the unary function pointer_to_unary_function <Arg, Result>(*_pfunc).
The second template function returns binary function pointer_to_binary_function <Arg1, Arg2, Result>(*_pfunc).
bind1st bind2nd的使用 || remove_if() - 飛不會 - 飛不會的博客 Remarks
A function pointer is a function object and may be passed to any Standard Template Library algorithm that is expecting a function as a parameter, but it is not adaptable. To use it with an adaptor, such as binding a value to it or using it with a negator, it must be supplied with the nested types that make such an adaptation possible. The conversion of unary and binary function pointers by the ptr_fun helper function allows the function adaptors to work with unary and binary function pointers.
bind1st bind2nd的使用 || remove_if() - 飛不會 - 飛不會的博客 Example
// functional_ptr_fun.cpp// compile with: /EHsc#include <vector>#include <algorithm>#include <functional>#include <cstring>#include <iostream>int main( ){ using namespace std; vector <char*> v1; vector <char*>::iterator Iter1, RIter; v1.push_back ( "Open" ); v1.push_back ( "up" ); v1.push_back ( "the" ); v1.push_back ( "pearly" ); v1.push_back ( "gates" ); cout << "Original sequence contains: " ; for ( Iter1 = v1.begin( ) ; Iter1 != v1.end( ) ; Iter1++ ) cout << *Iter1 << " "; cout << endl; // To search the sequence for "pearly" // use a pointer_to_function conversion RIter = find_if( v1.begin( ), v1.end( ), not1 ( bind2nd (ptr_fun ( strcmp ), "pearly" ) ) ); if ( RIter != v1.end( ) ) { cout << "The search for 'pearly' was successful.\n"; cout << "The next character string is: " << *++RIter << "." << endl; }}bind1st bind2nd的使用 || remove_if() - 飛不會 - 飛不會的博客 Output
Original sequence contains: Open up the pearly gates The search for 'pearly' was successful.The next character string is: gates.bind1st bind2nd的使用 || remove_if() - 飛不會 - 飛不會的博客 Requirements
Header: <functional>
bind1st bind2nd的使用 || remove_if() - 飛不會 - 飛不會的博客 See Also
Reference
Standard Template Library
Other Resources
<functional> Members