C++ STL 学习 :for_each与仿函数(functor)

C++ for_each构造函数和析构函数的调用,仿函数,lambda //for_each()调用三次析构函数   仿函数(functor),就是使一个类的使用看上去象一个函数。其实现就是类中实现一个operator(),这个类就有了类似函数的行为,就是一个仿函数类了。   有些功能的的代码,会在不同的成员函数中用到,想复用这些代码。     1)公共的函数,可以,这是一个解决方法,不过函数用到的一些变量,就可能成为公共的全局变量,再说为了复用这么一片代码,就 阅读详情

C++ STL 学习 :for_each与仿函数(functor)

  简单来将,仿函数(functor)就是一个重载了"()"运算符的struct或class,利用对象支持operator()的特性,来达到模拟函数调用效果的技术。
  我们平时对一个集合类遍历的时候,例如vector,是这样做的:
for(vector<int>::const_iterator iter = ivec.begin(); iter != ivec.end(); ++iter)
{
    //do your whatever you want here
}
例如下面的代码:
复制代码
#include <vector>
#include <iostream>

struct State
{
    State( int state ) : m_state( state ){}
    ~State() { std::cout << "~State(), m_state=" << m_state << std::endl; }

    void setState( int state ){ m_state = state; }
    int getState() const{ return m_state; }

    void print() const { std::cout << "State::print: " << m_state << std::endl; }

private:
    int m_state;
};

int main()
{
    std::vector<State*> vect;

    vect.push_back( new State(0) );
    vect.push_back( new State(1) );
    vect.push_back( new State(2) );
    vect.push_back( new State(3) );

       std::vector<State*>::iterator it( vect.begin() );
    std::vector<State*>::iterator ite( vect.end() );
    for ( ; it != ite; ++it )
    {
        (*it)->print();
    }
    
    
    system( "pause" );
    return 0;
}
复制代码

这里的for循环语句有点冗余,想到了std::for_each ,为了使用for_each,我们需要定义一个函数,如下:

void print( State* pstate )
{
    pstate->print();
}

于是就可以简化为下面代码:
std::for_each( vect.begin(), vect.end(), &print );

上面这段代码有点丑陋,看起来不太爽,主要是函数指针的原因。
在这种应用环境下,C++有仿函数来替代,我们定义一个仿函数,如下:

struct Printer
{
    template<typename T> void operator()( T* t ) { t->print(); }
};

于是就可以简化为下面代码:
std::for_each( vect.begin(), vect.end(), Printer() );

下面,我们初步看下 for_each 的STL源码实现: 

复制代码
 // TEMPLATE FUNCTION for_each

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);
    }
    
上面的代码看起来挺晕菜的,这里给出 effective STL 里面的一个实现,简单明了:

template< typename InputIterator, typename Function >
Function for_each( InputIterator beg, InputIterator end, Function f ) {
    while ( beg != end )
        f( *beg++ );
} // TEMPLATE FUNCTION for_each

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);
    }
    
上面的代码看起来挺晕菜的,这里给出 effective STL 里面的一个实现,简单明了:

template< typename InputIterator, typename Function >
Function for_each( InputIterator beg, InputIterator end, Function f ) {
    while ( beg != end )
        f( *beg++ );
}
复制代码

  其实for_each就是一个模板函数,将for循环语句封装起来,前面两个参数都是迭代器,第三个参数是使用一个函数指针(或仿函数),其功能是对每一个迭代器所指向的值调用仿函数。

上面代码还是有点冗余,因为为了使用for_each还要单独定义一个函数(或仿函数),不太清爽,
呵呵,stl早为我们准备好了 mem_fun 模板函数来解决这个一个问题,于是代码再次简化为:

std::for_each( vect.begin(), vect.end(), std::mem_fun( &State::print ) );

我们一起看看 mem_fun 的STL源码实现: 

复制代码
       // TEMPLATE FUNCTION mem_fun
template<class _Result,
    class _Ty> inline
    mem_fun_t<_Result, _Ty> mem_fun(_Result (_Ty::*_Pm)())
    {    // return a mem_fun_t functor adapter
    return (std::mem_fun_t<_Result, _Ty>(_Pm));
    }

mem_fun 函数实际上是调用 mem_fun_t 函数,我们接着深入看看 mem_fun_t,


        // TEMPLATE CLASS mem_fun_t
template<class _Result,
    class _Ty>
    class mem_fun_t
        : public unary_function<_Ty *, _Result>
    {    // functor adapter (*p->*pfunc)(), non-const *pfunc
public:
    explicit mem_fun_t(_Result (_Ty::*_Pm)())
        : _Pmemfun(_Pm)
        {    // construct from pointer
        }

    _Result operator()(_Ty *_Pleft) const
        {    // call function
        return ((_Pleft->*_Pmemfun)());
        }
private:
    _Result (_Ty::*_Pmemfun)();    // the member function pointer
    };

将上面这段代码定义的写的我们好看懂一点,如下:

        // TEMPLATE CLASS mem_fun_t
template< typename _Result, typename _Ty >
class mem_fun_t : public unary_function<_Ty *, _Result>
{    
    typedef _Result (_Ty::*_Pmemfun)();
public:
    explicit mem_fun_t( _Pmemfun& pfunc )
        : m_pfun( pfunc )
    {    // construct from pointer
    }

    _Result operator()(_Ty *_Pleft) const
    {    // call function
        return ( (_Pleft->*m_pfun)() );
    }

private:
    _Pmemfun m_pfun; // the member function pointer

};
复制代码

  这样就比较清晰了,定义了仿函数mem_fun_t内部定义了一个类成员函数指针,仿函数构造的时候将函数指针保存起来,当仿函数operator()被调用的时候,就通过与一个类的实例关联起来从而实现了类成员函数的调用。

  其调用流程是这样的,for_each把vector中的元素传送给mem_fun,mem_fun自己产生一个仿函数mem_fun_t,然后仿函数调用其重载的()。

  上述源码还有最后一个没有说明,就是unary_function,直接上源码:

复制代码
 // TEMPLATE STRUCT unary_function
template<class _Arg,
    class _Result>
    struct unary_function
    {    // base class for unary functions
    typedef _Arg argument_type;
    typedef _Result result_type;
    };
复制代码

就一个模板结构体。没有数据成员,非常简单。
最后,定义一个删除指针的仿函数:
struct DeletePointer
{
    template<typename T> void operator()( T* ptr ) const { delete ptr; }
};
然后调用,就一个逐一删除vector里面的所有元素了。
std::for_each( vect.begin(), vect.end(), DeletePointer() );

C++中的仿函数 更多文章欢迎访问 程序员小非 博客 定义 functor的英文解释为something that performs a function,即其行为类似函数的东西。C++中的仿函数是通过在类中重载()运算符实现,使你可以像使用函数一样来创建类的对象。 C中是怎么实现这个功能的 使用指针函数和回调函数,比如qsort的比较函数 #include <stdio.h> #include &... 阅读详情

相关推荐

C++仿函数深度解析:从STL应用到高阶编程实践

在C++编程中,可调用对象是实现算法复用和逻辑封装的核心概念。仿函数通过重载operator()运算符,将函数行为与对象特性相结合,其原理在于将状态和行为封装在类实例中,实现了比普通函数更强的表达能力。这一技术价值在于它完美支持策略模式和高阶函数,是连接面向对象与泛型编程的关键桥梁。在应用场景上,仿函数广泛用于STL算法定制、回调系统构建以及需要携带状态的复杂业务逻辑中。本文以STL算法和策略模式为例,深入探讨了仿函数在C++泛型编程中的高级应用,特别是如何通过模板化和状态管理实现代码的高度复用与解耦。

dechen6073的博客 370

STL学习笔记(4)- STL算法导论for_each和仿函数

STL提供了 for_each 函数,对容器某个范围内的提供统一的函数调用的函数。 下面是一个 for_each 的基本用法示例,将数组 vector 中的每一个元素内容* 2 使用 for_each 时,需要使用头文件 <algorithm> 具体代码如下: #include <iostream> #include <algorithm> #include &...

不会飞的纸飞机的博客 380

HBuilderX远程开发环境配置:Windows SSH连接实操

详细介绍如何在Windows系统中通过SSH连接远程服务器,配置HBuilderX进行高效远程开发,提升编码协作效率。全程实操演示,轻松掌握hbuilderx与远程环境的无缝对接。

weixin_35751194的博客 1192

foreach循环无数据

异常:后台能确定可以返回数据,且前台页面能看到数据条数,但是无法正常显示数据内容(如下图所示),且浏览器与控制台都没有报错信息。 从循环显示数据的代码来看,我们可以得知出现该问题的原因是:var的值与循环数据的变量名不一致,如下图中红色与黄色的标注内容 PS:var代表当前条目的变量名称,即是要循环集合的别名 解决方案:统一变量名即可。 ...

心若向阳 无谓悲伤 1142

HTML5期末大作业:水果超市网站设计——水果超市(6页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 网购商城设置网页

HTML5期末大作业:水果超市网站设计——水果超市(6页) HTML+CSS+JavaScript 学生DW网页设计作业成品 web课程设计网页规划与设计 网购商城设置网页 常见网页设计作业题材有 个人、 美食、 公司、 学校、 旅游、 电商、 宠物、 电器、 茶叶、 家居、 酒店、 舞蹈、 动漫、 明星、 服装、 体育、 化妆品、 物流、 环保、 书籍、 婚纱、 军事、 游戏、 节日、 戒烟、 电影、 摄影、 文化、 家乡、 鲜花、 礼品、 汽车、 其他 等网页设计题目, A+水平作业, 可满足大

1715

光模块封装工艺简介

光模块按照部件可以分为芯片、光器件、光模块三个层级;按照应用领域大概可分为电信应用、数通应用两个领域;按照内部器件的封装工艺可分为TO、Box、COB三大类。 但是,无论是哪种类型的光模块,其生产工艺基本上可以分为封装、测试两大块。   那什么叫做器件封装呢?我的理解器件封装就是利用胶水、焊料、机械、热量等手段把器件按照一定的先后次序结合形成一个整体的过程,就好像早上吃的煎饼,把面粉、鸡蛋、脆饼、烤肠、葱花等这些“器件”,按照一定的顺序,通过食用油、甜面酱、加热、卷起来等手段结合到一起,形成了美味的

qq_33253182的博客 2830

STL中的for_each()函数

for_each()函数是C++ STL中的一个遍历函数,函数原型如下: for_each(InputIterator first, InputIterator last, Function functor); 一般情况下使用的时候都是把first作为容器遍历的起始点指针,last是容器的末尾。重点提到的是functor(仿函数)。 仿函数是一种在模板类编程时的封装手法,本质上的仿函数是一种

Chasing Dream! 1万+

nmap、X-Scan漏洞扫描和Metasploit中用永恒之蓝漏洞入侵靶机并上传冰河

利用nmap、X-Scan扫描靶机的漏洞,在Metasploit中用扫描出的永恒之蓝漏洞入侵靶机,建立连接后上传冰河木马控制靶机,最后用冰河陷阱清除靶机的冰河木马,记一次完整的入侵控制实验。

m0_59302403的博客 4408

java 仿函数,C++ STL 学习 :for_each与仿函数(functor)(一)

C++ STL 学习 :for_each与仿函数(functor)(一)By zieckey( All right reserved!)先看wikipedia定义:A function object, also called a functor, functional, or functionoid,[1] is a computer programming construct allowing...

weixin_39673704的博客 125

安卓 实现灯光闪过效果

有个小需求,给按钮加一个灯光划过的效果,这样的需求一般有UI,肯定就找UI了要个gif图不就完事了,可是这次没有,好久自己做一个嘛。Web端的大佬实现很快,到安卓这边呢,百度一搜发现诶?怎么没有,好吧自己来一个 一切动效相关的不给图看都是耍流氓 所以俺不能这么干啊,OK!直接上效果图,再来解释下怎么实现的 效果就是这样子,怎么实现呢? 从图分析下,就是一个光写着重左边移动要右边循环嘛,这有啥难的?? 来看一看我的第一版,第二版 这是个什么?????一点都不像啊? 赶紧再问了问Web端大佬,噢,加了一个

SummerCloudXT的博客 1378

运行时安全引擎RSE

该博客重点介绍了运行时安全引擎(Runtime Security Engine,简称 RSE)与应用处理器(Application Processor,简称 AP)之间的关系。 根据 ARM 的参考设计,RSE 是位于同一芯片(die)上的一个独立核心,与 AP 和系统控制处理器(System Control Processor,简称 SCP)并列存在。RSE 为整个系统提供基本的安全保障和运行时服务,例如:可信启动(trusted boot)、度量启动(measured boot)、平台认证(platf

AI-安全-功耗 1364

C++ STL 学习 :for_each与仿函数(functor)(一)

C++ STL 学习 :for_each与仿函数(functor)(一) 摘自网络 作者: zieckey  时间: 2010-07-20 13:38:00 先看wikipedia定义: A function object, also called a functor, functional, or functionoid,[1]  is a computer programmin

tangle_zero的专栏 485

Far planner代码系列(2)

graph_decoder系列(2) 承接上文 我们接着来看decoder_node.cpp的代码部分 void GraphDecoder::Init() { /* initialize subscriber and publisher */ //graph_sub_ 订阅节点/robot_vgraph 其类型是visibility_graph_msg/Graph的消息 graph_sub_ = nh.subscribe("/robot_vgrap...

博客 1534

C++11 仿函数(functor) std::function std::bind

std::function是函数模板类(是一个类)。头文件 #include 是一个函数对象的包装器,函数。lamada表达式。绑定表达式或其他函数对象。指向成员函数和指向数据成员的指针。

q610098308的专栏 1673

基于STM32单片机智能循迹小车毕业设计

本文介绍了一种利用STM32F103C8T6单片机为控制核心,结合多种传感器以及PID算法实现循迹避障功能的智能小车。随着我国高科技水平的不断提高和工业自动化进程的不断推进,智能小车被广泛应用于各种玩具和其他产品的设计中,极大地丰富了人们的生活。本次设计利用反射式红外光电传感器探测路面黑线实现小车循迹,利用超声波测距传感器探测路径上的障碍,控制小车自动避障,整个系统具有自动循迹、自动避障、速度检测和无线遥控功能。其中,控制部分采用STM32F103C8T6单片机,STM32F103C8T6单片机是一

qq_48771816的博客 3974

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

C++ STL 学习 :更多仿函数(functor)(二)

By zieckey( All right reserved!) C++ STL 学习 :更多仿函数(functor)(二) C++标准程序库中提供了许多非常有用的预先定义好的的仿函数,了解这些将为我们的开发工作带来便利性和稳健性。 求反值: // TEMPLATE STRUCT negate templateclass _Ty>     struc

Damon_X的博客 612

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

C++仿函数:从STL算法到现代编程的灵活回调机制

在C++编程中,可调用对象是实现灵活回调与算法定制的核心概念。其原理是通过重载函数调用运算符,使类对象具备函数行为,从而封装状态与操作。这一技术价值在于突破了传统函数指针的局限,支持内联优化与状态保持,显著提升泛型编程效率。应用场景广泛覆盖STL算法定制、策略模式实现以及事件处理框架。本文聚焦仿函数(Functor)这一具体实现,深入解析其在STL算法中的实战应用,并与lambda表达式、std::function等现代特性对比,帮助开发者掌握构建高效、可复用代码的关键范式。

weixin_34221654的博客 302

文档:亲测可用解决vnc灰屏,黑屏,鼠标大黑叉情况

主要解决vnc-viewer灰屏,黑屏,鼠标大黑叉等现象,详细见文档。

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

浅谈:函数指针、仿函数和函数适配…

一,仿函数是什么 前几天写了篇博客——浅谈函数指针,主要讲我对函数指针的理解和应用经验。今天,翻看了《C++Primer Plus》第16章“函数对象”这一节,发现C++中还有比函数指针更高层次的抽象——functor,中文名为“仿函数”“类函数”或“函数对象”。它的实际就是“重载了'operator()'的类”,并兼容函数指针。如下: class Linear { private:     do

Sagittarius_Warrior的博客 1400
上一篇: 聊聊Linux中的线程本地存储(1)——什么是TLS
下一篇: 编译指示(Pragma Directives)
killmice
博客等级 码龄14年 119粉丝 54原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值