STL之函数对象和谓词

STL之函数对象和谓词

1.函数对象

重载函数调用操作符的类,其对象常称为函数对象(function object),即它们是行为类似函数的对象。一个类对象,表现出一个函数的特征,就是通过“对象名+(参数列表)”的方式使用一个类对象,如果没有上下文,完全可以把它看作一个函数对待。 
这是通过重载类的operator()来实现的。 
“在标准库中,函数对象被广泛地使用以获得弹性”,标准库中的很多算法都可以使用函数对象或者函数来作为自定的回调行为;

一元函数对象:函数参数1个; 
二元函数对象:函数参数2个;

2.谓词

一元谓词: 函数参数1个,函数返回值是bool类型,可以作为一个判断式

二元谓词: 函数参数2个,函数返回值是bool类型

谓词可以使一个仿函数,也可以是一个回调函数。

一元谓词举例如下
1.判断给出的string对象的长度是否小于6

bool GT6(const string &s)
{
return s.size() >= 6;
}
 
 
  • 1
  • 2
  • 3
  • 4

2.判断给出的int是否在3到8之间

bool Compare( int i )
{
return ( i >= 3 && i <= 8 );
}
 
 
  • 1
  • 2
  • 3
  • 4

二元谓词举例如下
1.比较两个string对象,返回一个bool值,指出第一个string是否比第二个短

bool isShorter(const string &s1, const string &s2)
{
return s1.size() < s2.size();
}
 
 
  • 1
  • 2
  • 3
  • 4

3.一元函数对象案例

//1普通类 重载 函数调用操作符
template <typename T>
void FuncShowElemt(T &t)  //普通函数 不能像 仿函数那样记录状态
{
    cout << t << " ";
};

void showChar(char &t)
{
    cout << t << " ";
}

//函数模板 重载 函数调用操作符
template <typename T>
class ShowElemt
{
public:
    ShowElemt()
    {
        n = 0;
    }
    void operator()(T &t)
    {
        n++;
        cout << t << " ";
    }
    void printCount()
    {
        cout << n << endl;
    }
public:
    int n;
};

//1 函数对象 基本使用
void main11()
{
    int a = 100;
    FuncShowElemt<int>(a); //普通的函数调用

    ShowElemt<int> showElemt; //函数对象 
    showElemt(a); //函数对象调用 
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

4.一元谓词案例

//1元谓词 例子
template <typename T>
class Isdiv
{
public:
    Isdiv(const T &divisor) //
    {
        this->divisor = divisor;
    }
    bool operator()(T &t)
    {
        return (t%divisor == 0);
    }
protected:
private:
    T divisor;
};

void main13()
{
    vector<int> v2;
    for (int i=10; i<33; i++)
    {
        v2.push_back(i);
    }
    vector<int>::iterator it;
    int a = 4;
    Isdiv<int> mydiv(a);
    // _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred)   //返回的是迭代器
    it = find_if(v2.begin(), v2.end(), Isdiv<int>(4));
    if (it != v2.end())
    {
        cout << "第一个被4整除的数是:" << *it << endl;
    }
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35

5.二元函数对象案例

template <typename T>
struct SumAdd
{
    T operator()(T &t1, T &t2)
    {
        return t1 + t2;
    }
};

template <typename T>
void printE(T &t)
{
    for (vector<int>::iterator it = t.begin(); it!=t.end(); it++ )
    {
        cout << *it << " ";
    }
}

void printVector(vector<int> &v)
{
    for (vector<int>::iterator it = v.begin(); it!=v.end(); it++ )
    {
        cout << *it << " ";
    }
}

void  main14()
{
    vector<int> v1, v2 ;
    vector<int> v3;
    v1.push_back(1);
    v1.push_back(2);
    v1.push_back(3);

    v2.push_back(4);
    v2.push_back(5);
    v2.push_back(6);

    v3.resize(10);

    //transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());
    /*
    template<class _InIt1,
    class _InIt2,
    class _OutIt,
    class _Fn2> inline
        _OutIt transform(_InIt1 _First1, _InIt1 _Last1,
        _InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
    */
    vector<int>::iterator it = transform(v1.begin(), v1.end(), v2.begin(),v3.begin(), SumAdd<int>());
    cout << *it << endl;
    printE(v3); 
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

6.二元谓词案例

void current(int &v)
{
    cout << v << " ";
}

bool MyCompare(const int &a, const int &b)
{
    return a < b;
}
void main15()
{
    vector<int> v(10);

    for (int i=0; i<10; i++)
    {
        v[i] = rand() % 100;
    }

    for_each(v.begin(), v.end(), current);
    printf("\n");
    sort(v.begin(), v.end(), MyCompare );

    printf("\n");
    for (int i=0; i<10; i++)
    {
        printf("%d ", v[i]);
    }
    printf("\n");
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

7.综合示例代码


#include <iostream>
using namespace std;

#include "string"
#include <vector>
#include <list>
#include "set"
#include <algorithm>
#include "functional"

//函数对象 类重载了()
template <typename T>
class ShowElemt
{
public:
    ShowElemt()
    {
        n = 0;
    }
    void operator()(T &t)
    {
        n ++;
        //printN();
        cout << t << " ";
    }
    void printN()
    {
        cout << "n:" << n << endl;
    }
protected:
private:
    int n;
};


//函数模板  ==函数
template <typename T>
void FuncShowElemt(T &t)
{
    cout << t << endl;
}

//普通函数
void FuncShowElemt2(int &t)
{
    cout << t << " ";
}

//函数对象 定义 ;  函数对象和普通函数的异同 
//
void main01()
{
    int a = 10;
    ShowElemt<int> showElemt;
    showElemt(a); //函数对象的()的执行 很像一个函数 //仿函数

    FuncShowElemt<int>(a);
    FuncShowElemt2(a);
}

//函数对象是属于类对象,能突破函数的概念,能保持调用状态信息
//函数对象的好处
// for_each算法中, 函数对象做函数参数
// for_each算法中, 函数对象当返回值
void main02()
{
    vector<int> v1;
    v1.push_back(1);
    v1.push_back(3);
    v1.push_back(5);

    for_each(v1.begin(), v1.end(), ShowElemt<int>()); //匿名函数对象 匿名仿函数
    cout << endl;
    for_each(v1.begin(), v1.end(), FuncShowElemt2); //通过回调函数  谁使用for_each 谁去填写回调函数的入口地址


    ShowElemt<int> show1;
    //函数对象 做函数参数 
    /*
        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);
            return (_For_each(_Unchecked(_First), _Unchecked(_Last), _Func));
        }
    */
    //1 for_each算法的 函数对象的传递 是元素值传递 ,不是引用传递
    for_each(v1.begin(), v1.end(), show1);
    show1.printN();

    cout << "通过for_each算法的返回值看调用的次数" << endl;
    show1 = for_each(v1.begin(), v1.end(), show1);
    show1.printN();

    //结论 要点: 分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象) 是stl算法入门的重要点
}

template<typename T>
class IsDiv
{
public:
    IsDiv(const T &divisor)
    {
        this->divisor = divisor;
    }
    bool operator()(T  &t)
    {
        return (t%divisor == 0);
    }

protected:
private:
    T divisor;
};

void main03()
{
    vector<int> v2;
    for (int i=10; i<33; i++)
    {
        v2.push_back(i);
    }
    int a = 4;
    IsDiv<int> myDiv(a);

    //find_if(v2.begin(), v2.end(), myDiv );

    /*
    template<class _InIt,
    class _Pr> inline
        _InIt find_if(_InIt _First, _InIt _Last, _Pr _Pred)
    {   // find first satisfying _Pred
        _DEBUG_RANGE(_First, _Last);
        _DEBUG_POINTER(_Pred);
        return (_Rechecked(_First,
            _Find_if(_Unchecked(_First), _Unchecked(_Last), _Pred)));
    }
    //find_if返回值是一个迭代器 
    //要点: 分清楚 stl算法返回的值是迭代器 还是 谓词(函数对象) 是stl算法入门的重要点
    */

    vector<int>::iterator it;
    it = find_if(v2.begin(), v2.end(), IsDiv<int>(a) );
    if (it == v2.end())
    {
        cout << "容器中没有被4整除的元素" << endl;
    }
    else
    {
        cout <<"第一个是被4整除的元素是:" << *it << endl;
    }

}


//二元函数对象
template <typename T>
class SumAdd
{
public:
    T operator()(T t1, T t2)
    {
        return t1 + t2;
    }
};

void main04()
{
    //v1 v2 ==> v3
    vector<int> v1, v2;
    vector<int> v3;
    v1.push_back(1);
    v1.push_back(3);
    v1.push_back(5);

    v2.push_back(2);
    v2.push_back(4);
    v2.push_back(6);

    v3.resize(10);

    /*
    template<class _InIt1,
    class _InIt2,
    class _OutIt,
    class _Fn2> inline
        _OutIt transform(_InIt1 _First1, _InIt1 _Last1,
        _InIt2 _First2, _OutIt _Dest, _Fn2 _Func)
    {   // transform [_First1, _Last1) and [_First2, ...) with _Func
        _DEBUG_RANGE(_First1, _Last1);
        _DEBUG_POINTER(_Dest);
        _DEBUG_POINTER(_Func);
        if (_First1 != _Last1)
            return (_Transform2(_Unchecked(_First1), _Unchecked(_Last1),
            _First2, _Dest, _Func,
            _Is_checked(_Dest)));
        return (_Dest);
    }

    //transform 把运算结果的 迭代器的开始位置 返回出来 
    */

    transform(v1.begin(), v1.end(), v2.begin(), v3.begin(), SumAdd<int>() );

    for (vector<int>::iterator it=v3.begin(); it!=v3.end(); it++ )
    {
        cout << *it << " ";
    }
    cout << endl;
}


bool MyCompare(const int &a, const int &b)
{
    return a < b; //从小到大
}

void main05()
{
    vector<int> v1(10);

    for (int i=0; i<10; i++)
    {
        int tmp = rand() %100;
        v1[i] = tmp;
    }

    for (vector<int>::iterator it=v1.begin(); it!=v1.end(); it++ )
    {
        cout << *it <<" ";
    }
    cout << endl;
    for_each(v1.begin(), v1.end(), FuncShowElemt2);
    cout << endl;

    sort(v1.begin(), v1.end(), MyCompare);
    for_each(v1.begin(), v1.end(), FuncShowElemt2);
    cout << endl;
}

struct CompareNoCase
{
    bool operator()(const string &str1, const string &str2)
    {
        string str1_ ;
        str1_.resize(str1.size() );
        transform(str1.begin(), str1.end(), str1_.begin(), tolower ); //预定义函数对象 

        string str2_ ;
        str2_.resize(str2.size() );
        transform(str2.begin(), str2.end(), str2_.begin(), tolower ); //预定义函数对象 

        return (str1_ < str2_); // 从小到大进行排序
    }
};
void  main06()
{
    set<string> set1;
    set1.insert("bbb");
    set1.insert("aaa");
    set1.insert("ccc");
    set<string>::iterator it = set1.find("aAa"); //find函数 默认 区分大小写
    if (it == set1.end())
    {
        cout << " 没有 查找到 aaa " << endl;
    }
    else
    {
        cout << " 查找到 aaa " << endl;
    }

    set<string, CompareNoCase> set2;
    set2.insert("bbb");
    set2.insert("aaa");
    set2.insert("ccc");

    set<string, CompareNoCase>::iterator it2 = set2.find("aAa");
    if (it2 == set2.end())
    {
        cout << " 没有 查找到 aaa " << endl;
    }
    else
    {
        cout << " 不区分大小的的查找  查找到 aaa " << endl;
    }

}

void main1111()
{
    //main01(); //函数对象基本概念
    //main02(); //函数对象的好处 函数对象做函数参数 函数对象做返回值

    //main03(); //一元谓词
    //main04(); //二元函数对象 和二元谓词
    //main05(); //二元函数对象 和二元谓词
    main06(); //二元谓词在set集合中的应用
    cout<<"hello..."<<endl;
    system("pause");
    return ;
}
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242
  • 243
  • 244
  • 245
  • 246
  • 247
  • 248
  • 249
  • 250
  • 251
  • 252
  • 253
  • 254
  • 255
  • 256
  • 257
  • 258
  • 259
  • 260
  • 261
  • 262
  • 263
  • 264
  • 265
  • 266
  • 267
  • 268
  • 269
  • 270
  • 271
  • 272
  • 273
  • 274
  • 275
  • 276
  • 277
  • 278
  • 279
  • 280
  • 281
  • 282
  • 283
  • 284
  • 285
  • 286
  • 287
  • 288
  • 289
  • 290
  • 291
  • 292
  • 293
  • 294
  • 295
  • 296
  • 297
  • 298
  • 299
  • 300
  • 301
  • 302
  • 303
  • 304

8.预定义函数对象

标准模板库STL提前定义了很多预定义函数对象,#include <functional> 必须包含。

//1使用预定义函数对象:
//类模板plus<> 实现了: 不同类型的数据进行加法运算
void main41()
{
    plus<int> intAdd;
    int x = 10;
    int y = 20;
    int z = intAdd(x, y); //等价于 x + y 
    cout << z << endl;

    plus<string> stringAdd;
    string myc = stringAdd("aaa", "bbb");
    cout << myc << endl;

    vector<string> v1;
    v1.push_back("bbb");
    v1.push_back("aaa");
    v1.push_back("ccc");
    v1.push_back("zzzz");

    //缺省情况下,sort()用底层元素类型的小于操作符以升序排列容器的元素。
    //为了降序,可以传递预定义的类模板greater,它调用底层元素类型的大于操作符:
    cout << "sort()函数排序" << endl;;
    sort(v1.begin(), v1.end(), greater<string>() ); //从大到小
    for (vector<string>::iterator it=v1.begin(); it!=v1.end(); it++ )
    {
        cout << *it << endl;
    }
}

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

8.1算术函数对象

预定义的函数对象支持加、减、乘、除、求余和取反。调用的操作符是与type相关联的实例

//加法:plus<Types>
plus<string> stringAdd;
sres = stringAdd(sva1,sva2);

减法:minus<Types>
乘法:multiplies<Types>
除法divides<Tpye>
求余:modulus<Tpye>
取反:negate<Type>
negate<int> intNegate;
ires = intNegate(ires);
Ires= UnaryFunc(negate<int>(),Ival1);
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

8.2关系函数对象

等于equal_to<Tpye>
equal_to<string> stringEqual;
sres = stringEqual(sval1,sval2);
不等于not_equal_to<Type>
大于 greater<Type>
大于等于greater_equal<Type>
小于 less<Type>
小于等于less_equal<Type>
 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
void main42()
{
    vector<string> v1;
    v1.push_back("bbb");
    v1.push_back("aaa");
    v1.push_back("ccc");
    v1.push_back("zzzz");
    v1.push_back("ccc");
    string s1 = "ccc";
    //int num = count_if(v1.begin(),v1.end(), equal_to<string>(),s1);
    int num = count_if(v1.begin(),v1.end(),bind2nd(equal_to<string>(), s1));
    cout << num << endl;
} 

 
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

8.3逻辑函数对象

逻辑与 logical_and<Type>
logical_and<int> indAnd;
ires = intAnd(ival1,ival2);
dres=BinaryFunc( logical_and<double>(),dval1,dval2);
逻辑或logical_or<Type>
逻辑非logical_not<Type>
logical_not<int> IntNot;
Ires = IntNot(ival1);
Dres=UnaryFunc( logical_not<double>,dval1);
 
 
    • 0
      点赞
    • 4
      收藏
      觉得还不错? 一键收藏
    • 0
      评论
    谓词函数是一种返回布尔值的函数,通常用于STL算法中的筛选、排序、查找等操作。在STL算法中,谓词函数可以作为参数传递给算法,用于指定算法的行为。 在C++中,谓词函数可以是函数指针、函数对象或者lambda表达式,只要它们返回一个布尔值即可。下面是一个谓词函数的示例: ```c++ bool isEven(int n) { return n % 2 == 0; } ``` 在这个示例中,我们定义了一个名为 `isEven` 的函数,它接受一个整数参数 `n`,并返回一个布尔值表示 `n` 是否为偶数。 下面是一个使用谓词函数的示例,在这个示例中,我们使用STL算法 `std::find_if` 查找一个数组中的第一个偶数: ```c++ #include <iostream> #include <algorithm> #include <vector> bool isEven(int n) { return n % 2 == 0; } int main() { std::vector<int> v = {1, 3, 5, 2, 4, 6}; auto it = std::find_if(v.begin(), v.end(), isEven); if (it != v.end()) { std::cout << "The first even number is: " << *it << std::endl; } else { std::cout << "No even number found" << std::endl; } return 0; } ``` 在这个示例中,我们定义了一个名为 `v` 的整数向量,并使用STL算法 `std::find_if` 查找第一个偶数。我们将谓词函数 `isEven` 作为第三个参数传递给 `std::find_if` 算法,用于指定查找的条件。 当我们运行这个程序时,输出应该是: ``` The first even number is: 2 ``` 这个示例演示了如何使用谓词函数STL算法中指定条件。在实际编程中,谓词函数通常用于筛选、排序、查找等操作。

    “相关推荐”对你有帮助么?

    • 非常没帮助
    • 没帮助
    • 一般
    • 有帮助
    • 非常有帮助
    提交
    评论
    添加红包

    请填写红包祝福语或标题

    红包个数最小为10个

    红包金额最低5元

    当前余额3.43前往充值 >
    需支付:10.00
    成就一亿技术人!
    领取后你会自动成为博主和红包主的粉丝 规则
    hope_wisdom
    发出的红包
    实付
    使用余额支付
    点击重新获取
    扫码支付
    钱包余额 0

    抵扣说明:

    1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
    2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

    余额充值