一.函数目标概念

概念:

重载函数调用操作符的类,其目标常称为函数目标
函数目标运用重载的()时,行为类似函数调用,也叫仿函数

实质:

函数目标(仿函数)是一个类,不是一个函数

特点

  • 函数目标在运用时,能够像一般函数那样调用,能够有参数,能够有回来值;
  • 函数目标超出一般函数的概念,函数目标能够有自己的状况;
  • 函数目标能够作为参数传递;

函数目标能够像一般函数相同被调用,并且能够承受参数和回来值。经过重载函数调用操作符 operator(),函数目标能够在运用时表现得像函数相同。

函数目标的一个优势是它能够具有自己的状况。因为函数目标实际上是一个类的目标,所以它能够具有成员变量,这些变量能够在每次调用时坚持状况并进行更新。这使得函数目标能够在多次调用之间维护一些信息。

此外,函数目标还能够作为参数传递给其他函数。许多规范库的算法函数,例如 std::sortstd::transform 等,能够承受函数目标作为参数,以界说算法的具体操作。经过将函数目标传递给其他函数,咱们能够完成更灵敏、可定制的功用。

以下是一个简略的示例,展现了函数目标的用法:

#include <iostream>
class MyFunctor
{
public:
    void operator()(int x) const
    {
        // 在回调时输出消息
        std::cout << "Function object called with " << x << std::endl;
    }
};
void callWithFunctor(const MyFunctor& functor, int value)
{
    functor(value);  // 调用函数目标
}
int main()
{
    MyFunctor functor;
    callWithFunctor(functor, 42);  // 传递函数目标给函数,并进行调用
    return 0;
}

在上述示例中,MyFunctor 是一个函数目标,咱们将它作为参数传递给 callWithFunctor 函数,并在函数内部调用函数目标。

总结来说,函数目标能够像一般函数相同被调用,能够承受参数和回来值,能够具有自己的状况,并能够作为参数传递给其他函数,这使得函数目标在编程中非常有用和灵敏。


函数目标比较于一般函数具有一个重要的优势,那就是函数目标能够具有自己的状况。这意味着函数目标能够在多次调用之间记录和维护自己的内部数据。

一般函数是无状况的,它们不会保留任何关于之前调用的信息。每次调用函数时,它们仅仅依据传入的参数履行相应的操作,并回来成果。

而函数目标则能够在每次调用时坚持状况,并依据状况的改变来改变行为。这种状况是经过函数目标的成员变量来完成的。函数目标的成员变量能够记录在调用过程中需要耐久化的数据,而这些数据会在不同的函数调用之间持续存在。

这种函数目标的状况能够非常有用。它允许咱们在不同的调用之间共享和利用数据,从而完成更杂乱的行为。例如,咱们能够运用函数目标来完成一个计数器,每次调用添加计数值,并在后续的调用中运用该值。

以下是一个简略的示例,展现了函数目标中保存状况的功用:

#include <iostream>
class Counter
{
public:
    Counter() : count(0) {}
    int operator()()
    {
        return ++count;
    }
private:
    int count;
};
int main()
{
    Counter counter;
    std::cout << counter() << std::endl;  // 输出:1
    std::cout << counter() << std::endl;  // 输出:2
    std::cout << counter() << std::endl;  // 输出:3
    return 0;
}

在上述示例中,Counter 是一个函数目标,它经过重载函数调用操作符 operator() 来完成计数的功用。每次调用 Counter 目标时,计数器的值会添加,并回来新的计数值。

总结而言,函数目标比较一般函数具有自己的状况,这使得它们能够在多次调用之间坚持数据,并依据状况的改变改变行为。这种功用使得函数目标在许多运用场景中非常有用,例如完成计数器、缓存等。

二.谓词

概念:

  • 回来bool类型的仿函数称为谓词
  • 假如operator()承受一个参数,那么叫做一元谓词
  • 假如operator()承受两个参数,那么叫做二元谓词

回来 bool 类型的仿函数被称为谓词(Predicate)。谓词一般用于对某些条件进行判别,并回来相应的布尔值。

此外,依据 operator() 承受的参数数量,能够将谓词进一步分类为一元谓词(Unary Predicate)和二元谓词(Binary Predicate)。

  • 一元谓词是指 operator() 只承受一个参数的谓词。它用于对单个目标进行判别,回来一个布尔值。一元谓词一般用于像 std::find_ifstd::remove_if 等算法中。
  • 二元谓词是指 operator() 承受两个参数的谓词。它用于对两个目标进行比较或判别,回来一个布尔值。二元谓词一般用于像 std::sortstd::find 等算法中,用于指定排序规矩或比较条件。

经过运用谓词,咱们能够灵敏地对目标进行条件判别和过滤。

以下是一个简略的示例,展现了一元谓词和二元谓词的概念:

#include <iostream>
#include <vector>
#include <algorithm>
// 一元谓词
struct IsEven
{
    bool operator()(int n) const
    {
        return n % 2 == 0;
    }
};
// 二元谓词
struct IsLess
{
    bool operator()(int a, int b) const
    {
        return a < b;
    }
};
int main()
{
    std::vector<int> numbers = { 1, 2, 3, 4, 5 };
    // 运用一元谓词查找第一个偶数
    auto it = std::find_if(numbers.begin(), numbers.end(), IsEven());
    if (it != numbers.end())
    {
        std::cout << "First even number: " << *it << std::endl;
    }
    // 运用二元谓词排序
    std::sort(numbers.begin(), numbers.end(), IsLess());
    // 输出排序成果
    std::cout << "Sorted numbers: ";
    for (int num : numbers)
    {
        std::cout << num << " ";
    }
    std::cout << std::endl;
    return 0;
}

在上述示例中,IsEven 是一个一元谓词,经过重载 operator() 来判别一个数字是否为偶数。IsLess 是一个二元谓词,经过重载 operator() 完成了两个数字的比较操作。

咱们在主函数中运用了一元谓词来查找第一个偶数,并运用二元谓词对数组进行排序。

总结来说,回来 bool 类型的函数目标被称为谓词。依据 operator() 承受的参数数量,谓词能够进一步分类为一元谓词和二元谓词。谓词在规范库的算法中很多运用,用于自界说比较和条件判别。


find_if

std::find_if 是 C++ 规范库中的一个算法函数,它的作用是在给定的范围内查找满意指定条件的元素,并回来第一个满意条件的元素的迭代器。

函数签名如下所示:

template <class InputIt, class UnaryPredicate>
InputIt find_if(InputIt first, InputIt last, UnaryPredicate p);

参数说明:

  • firstlast:表明要查找的元素范围,first 表明范围的开始方位,last 表明范围的完毕方位(不包含在范围内)。
  • p:一个一元谓词,用于判别元素是否满意条件。

函数回来值是一个迭代器,指向范围内第一个满意条件的元素,假如没有找到满意条件的元素,则回来 last

以下是一个简略的示例,展现了 std::find_if 的运用:

#include <iostream>
#include <vector>
#include <algorithm>
struct IsEven
{
    bool operator()(int n) const
    {
        return n % 2 == 0;
    }
};
int main()
{
    std::vector<int> numbers = { 1, 2, 3, 4, 5 };
    // 运用一元谓词查找第一个偶数
    auto it = std::find_if(numbers.begin(), numbers.end(), IsEven());
    if (it != numbers.end())
    {
        std::cout << "First even number: " << *it << std::endl;
    }
    return 0;
}

在上述示例中,咱们界说了一个一元谓词 IsEven,用于判别一个数字是否为偶数。然后,咱们运用 std::find_if 函数在 numbers 容器中查找第一个满意条件的偶数,并输出成果。

值得注意的是,std::find_if 在查找到满意条件的元素后,会当即中止查找并回来该元素的迭代器。假如要查找出多个满意条件的元素,能够运用 std::find_if 结合其他算法函数或循环进行迭代查找。

三.内建函数目标

当涉及到内建函数目标时,能够依据它们的功用将它们分为三类: 算术函数目标、逻辑函数目标和联系函数目标。

  1. 算术函数目标:

    • std::plus: 加法操作。
    • std::minus: 减法操作。
    • std::multiplies: 乘法操作。
    • std::divides: 除法操作。
    • std::modulus: 取模操作。
  2. 逻辑函数目标:

    • std::logical_and: 逻辑与操作。
    • std::logical_or: 逻辑或操作。
    • std::logical_not: 逻辑非操作。
  3. 联系函数目标:

    • std::less: 小于比较。
    • std::less_equal: 小于等于比较。
    • std::greater: 大于比较。
    • std::greater_equal: 大于等于比较。
    • std::equal_to: 等于比较。
    • std::not_equal_to: 不等于比较。

这些函数目标能够经过重载 operator() 来履行特定的操作或比较,它们被设计为与规范库算法一同运用,以供给通用的功用。经过运用这些函数目标,咱们能够以一种通用且灵敏的方式处理算术、逻辑和联系操作。

当涉及到内建函数目标时,咱们能够经过以下示例来展现它们的运用:

  1. 算术函数目标:
#include <iostream>
#include <functional>
int main() {
    std::plus<int> add;
    int a = 5, b = 10;
    int result = add(a, b);
    std::cout << "Addition result: " << result << std::endl;  // 输出:15
    return 0;
}

在上述示例中,咱们运用了 std::plus 函数目标来履行加法操作,将数字 ab 相加,并将成果存储result 变量中。

  1. 逻辑函数目标:
#include <iostream>
#include <functional>
int main() {
    std::logical_and<bool> logicAnd;
    bool value1 = true, value2 = false;
    bool result = logicAnd(value1, value2);
    std::cout << "Logical AND result: " << std::boolalpha << result << std::endl;  // 输出:false
    return 0;
}

在上述示例中,咱们运用了 std::logical_and 函数目标来履行逻辑与操作,对 value1value2 进行逻辑与运算,并将成果存储在 result 变量中。

  1. 联系函数目标:
#include <iostream>
#include <functional>
int main() {
    std::less<int> lessThan;
    int a = 5, b = 10;
    bool result = lessThan(a, b);
    std::cout << "Less than result: " << std::boolalpha << result << std::endl;  // 输出:true
    return 0;
}

在上述示例中,咱们运用了 std::less 函数目标来履行小于比较,判别 a 是否小于 b,并将成果存储在 result 变量中。

这些示例演示了如何运用内建函数目标进行算术、逻辑和联系操作。您能够经过实例化恰当的函数目标类模板,然后将其用作函数调用,以便履行所需的操作或比较。

这些函数目标在规范库的算法和其他运用场景中非常有用。

函数目标 用途 示例
std::plus 加法操作 std::plus()(2, 3) // 输出:5
std::minus 减法操作 std::minus()(5, 2) // 输出:3
std::multiplies 乘法操作 std::multiplies()(3, 4) // 输出:12
std::divides 除法操作 std::divides()(10, 2) // 输出:5
std::modulus 取模操作 std::modulus()(10, 3) // 输出:1
std::logical_and 逻辑与操作 std::logical_and()(true, false) // 输出:false
std::logical_or 逻辑或操作 std::logical_or()(true, false) // 输出:true
std::logical_not 逻辑非操作 std::logical_not()(true) // 输出:false
std::less 小于比较 std::less()(2, 5) // 输出:true
std::less_equal 小于等于比较 std::less_equal()(5, 5) // 输出:true
std::greater 大于比较 std::greater()(5, 2) // 输出:true
std::greater_equal 大于等于比较 std::greater_equal()(5, 5) // 输出:true
std::equal_to 相等比较 std::equal_to()(2, 2) // 输出:true
std::not_equal_to 不等比较 std::not_equal_to()(2, 5) // 输出:true