函数对象与仿函数(function object and functor)

摘要:
此外,functionobject=function 2。函数对象(函子)可以用四种方式实现:函数指针、lambda表达式、由具有成员函数运算符()的类创建的对象,以及由具有转换函数的类创建并可以将自身转换为pointtofunction的对象。3.1函数指针使用函数指针作为“传递给算法的函数类型实际参数”。访问说明符包括public、protected和private。

part 1. 仿函数在STL组件中的关系

  如下图:

函数对象与仿函数(function object and functor)第1张

  # 仿函数配合算法完成不同的策略变化。

  # 适配器套接仿函数。

part 2. 仿函数介绍

  传递给算法的“函数型实参”不一定得是函数,可以是行为类似函数的对象。这种对象称为函数对象(function object),或称为仿函数(functor)。——《STL标准库(第2版)》 P233

  1. 函数对象 = 仿函数。并且,function object = functor

  2. 函数对象(仿函数)有四种实现方式:函数指针(fucntion pointer)、lambda表达式、“带有成员函数 operator()”的class建立的object、“带有转换函数可以将自己转换为 pointer to function”的class所建立的object。

  2.1 仿函数的实现原理:向算法传递的,终究是个函数。以上四种方式被调用时,终究是个函数。

  3. 下面的所有例子,均为 vector 容器排序,但是采用不同的函数对象实现方式。

  3.1 函数指针(function pointer)

  使用函数指针作为“传递给算法的‘函数型实参’”。

bool compareLength(const string& lhs, const string& rhs)
{
    return lhs.size() > rhs.size();
}

int main()
{
    vector<string> v = { "I", "love", "you" };
    sort(v.begin(), v.end(), compareLength);
    for(auto &s : v)
        cout << s << " ";
    return 0;
}
// 输出结果:
// love you I

  3.2 lambda表达式

  lambda 是一种隐式的预定义函数对象。

  使用 lambda表达式 作为“传递给算法的‘函数型实参’”。

int main()
{
    vector<string> v = { "I", "love", "you" };

    sort(v.begin(), v.end(), 
        [](const string& lhs, const string& rhs) 
            { return lhs.size() > rhs.size(); });

    for(auto &s : v)
        cout << s << " ";
    return 0;
}
// 输出结果:
// love you I

   

  3.3 “带有成员函数 operator()”的class/struct建立的object

  根据个人经验,如果不考虑类内访问权限,在这里使用 struct 是写更少代码的写法。因为 class 默认的访问权限是 private ,所以还要多谢一行 public:。也就是说,用 class 你要这样写:

class CompareSize
{
public:
    bool operator() (const string& lhs, const string& rhs)
    {
        return lhs.size() > rhs.size();
    }
};

  如果用 struct 你要这样写:

struct CompareSize
{
    bool operator() (const string& lhs, const string& rhs)
    {
        return lhs.size() > rhs.size();
    }
};

  使用“带有成员函数 operator()”的class/struct建立的object 作为 “传递给算法的‘函数型实参’” 的完整代码如下:

struct CompareSize
{
    bool operator() (const string& lhs, const string& rhs)
    {
        return lhs.size() > rhs.size();
    }
};

int main()
{
    vector<string> v = { "I", "love", "you" };
    sort(v.begin(), v.end(), CompareSize());
    for(auto &s : v)
        cout << s << " ";
    return 0;
}
// 输出结果:
// love you I

  3.3.1 用 struct 还是 class ?

  使用 class 和 struct 定义类唯一的区别就是默认的访问权限——《C++ primer (5th)》 P241

  所谓默认访问权限:定义在第一个访问说明符之前的成员,使用默认的访问权限。访问说明符有 public、protected、private。

  3.3.2 用 lambda表达式 还是 functor?

  首先,functor 泛指“带有成员函数 operator()”的 class/struct 建立的 object。其次,在语义明确,代码结构短小变量生存周期清晰,不追求复用的前提下,使用 lambda;否则使用 functor

  

  3.4“带有转换函数可以将自己转换为 pointer to function”的class所建立的object

  (下次再写)

part 3. 仿函数适配器

  (下次再写)

免责声明:文章转载自《函数对象与仿函数(function object and functor)》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇H5动画开发快车道python3 int() 各数据类型转int下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

Unity3D脚本语言UnityScript初探

译者注: Unity3D中支持三种语言:JavaScript、C#、Boo,很多人不知道如何选择,通过这篇译文,我们可以搞清楚这三者语言的来龙去脉,对选择主语言有一定的借鉴意义。 首先,Unity是基于Mono也就是.Net的运行环境的,所以它肯定支持C#;然后,Unity团队自行开发了一种Boo的语言;后面可能考虑到用户的接受程度的问题,又开发了类似J...

利用Elasticsearch搭建全球域名解析记录

前言 数据来源,由Rapid7收集并提供下载https://scans.io/study/sonar.fdns 下载Elasticsearch 2.3 ElasticSearch是一个基于Lucene开发的搜索服务器,具有分布式多用户的能力,ElasticSearch是用Java开发的开源项目(Apache许可条款),基于Restful Web接口,能够...

024. asp.net中第一次使用GridView (设置鼠标经过时更换背景色)

1. 前端HTML代码 <%@ Page Language="C#" AutoEventWireup="true" CodeFile="Index.aspx.cs" Inherits="Index" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "ht...

ElasticSearch的基本原理与用法

一、简介 ElasticSearch和Solr都是基于Lucene的搜索引擎,不过ElasticSearch天生支持分布式,而Solr是4.0版本后的SolrCloud才是分布式版本,Solr的分布式支持需要ZooKeeper的支持。 这里有一个详细的ElasticSearch和Solr的对比:http://solr-vs-elasticsearch.co...

C# POST multipart/form-data 方式提交数据

一.提交方法 /// <summary> /// MultipartFormData Post方式提交 /// </summary> /// <param name="url"></param> /// <param name="kVD...

加载配置文件

前言:如果我们需要调用某个方法,其中的参数为可更改,我们最好是采用配置文件的方式来写,这样便于管理 比如我在写一个通过SFTP连接服务器的环节 public class SFTPUtil { private static Logger log=Logger.getLogger(SFTPUtil.class.getName());...