皮皮网

【分时画线源码】【maven源码包】【iherb溯源码】std::bind 源码

2024-12-29 05:35:31 来源:铁笼指标源码

1.C++11中function和bind的用法
2.C++模板元编程&函数柯里化初探
3.C++11中的std::function和std::bind
4.第六节 std::bind 绑定器
5.从示例到源码深入了解std::ref

std::bind 源码

C++11中function和bind的用法

       在C++中,处理回调函数时,std::function和std::bind为处理可回调对象提供了便利。这两种工具分别用于封装和适应可调用对象的参数列表。

       std::function的用法

       这个类似于C语言的函数指针,包含在头文件中。分时画线源码它支持保存普通函数、lambda表达式以及非重载的成员函数。例如:

       保存普通函数:std::function func;

       保存lambda表达式:func = [](double a, double b) { return a + b; };

       保存成员函数(需注意,不能直接保存重载的成员函数):非重载成员func = &MyClass::myMethod;

       std::bind的用法

       std::bind是一个通用函数适配器,允许你根据需要调整可调用对象的参数。其基本形式是:auto newCallable = std::bind(callable, arg_list);

       这里的arg_list是参数列表,可以包含占位符(如_n)来表示新的可调用对象的参数位置。例如:newCallable(, _1, _2)会调用callable,将传递给第一个参数,_1和_2分别传递给后续的参数。

       总结

       std::function提供了三种方式来存储可调用对象:普通函数、lambda和非重载成员函数。而std::bind则用于处理参数适配,特别在处理重载成员函数时必不可少。通过这些工具,你可以根据具体需求灵活传递参数。

       如果你对C/C++和Linux系统开发感兴趣,maven源码包特别是服务器端开发,可以点击链接深入了解:[C/C++服务器开发](服务链接)

C++模板元编程&函数柯里化初探

       本文非教程,仅用于记录一些想法。在担任本科生C++助教时,我了解到函数柯里化,思考如何实现自动函数柯里化。恰好之前研究过std::bind,我想到可以通过保存参数的方式实现。尝试了一种方法,但发现通过vector保存参数会增加复制开销,且参数仅能是值,不能是引用。此外,如果调用时参数个数写错,只有运行时才能发现。进一步思考后,我意识到使用lambda构造代码可以简单暴力地解决这一问题。

       起初的实现仅支持int(int, int, int)类型的函数,我为此添加了一些自动适配功能,主要利用auto代替手动指定模板参数。然而,由于函数模板不支持偏特化,iherb溯源码我最终使用类模板实现。这样,看起来可以使用了,但函数参数个数仍需手动指定(Currier<4>)。为了解决这一问题,我利用R(*)(Args...)匹配函数参数,从而自动计算参数个数。

       总结而言,通过上述方法,我们不仅实现了自动函数柯里化,还能根据实际需求灵活地处理不同数量的参数。尽管面临一些挑战,如增加复制开销和参数类型限制,但通过创新的实现策略,我们能够有效解决这些问题。此探索不仅加深了对C++模板元编程的理解,也为实际编程中实现自动函数柯里化提供了参考。

C++中的std::function和std::bind

       C++中的std::funC++tion和std::bind一、可调用对象

       可调用对象有以下几种定义:

       是一个函数指针。

       是一个具有operator()(运算符重载)成员函数的类对象

       可被转换成函数指针的类对象

       一个类成员函数指针

       &emsp;&emsp;C++中==可调用对象==虽然都有一个比较统一的操作形式,但是定义方法五花八门,这样就导致使用统一的湖北棋牌源码方式保存可调用对象或者传递可调用对象时,会十分繁琐。C++中提供了std::function和std::bind统一了可调用对象的各种操作。

       不同的类型可能具有相同的调用形式,如:

//?普通函数int?add(int?a,?int?b){ return?a+b;}?//?lambda表达式auto?mod?=?[](int?a,?int?b){ ?return?a?%?b;}//?函数对象类struct?divide{ int?operator()(int?denominator,?int?divisor){ return?denominator/divisor;}};

       上述三种可调用对象虽然类型不同,但是共享用一种调用形式:

int(int,int)

       std::function就可以将上述类型保存起来,如下:

std::function<int(int?,int)>?a?=?add;?std::function<int(int?,int)>?b?=?mod?;?std::function<int(int?,int)>?c?=?divide();二、std::function

       std::function是一个可调用对象包装器,是一个类模板,可以容纳除了类成员函数指针之外的所有可调用对象。它可以用统一的方式处理函数、函数对象、函数指针,并允许保存和延迟它们的执行。

       定义格式:std::function<函数类型>

       std::function可以取代函数指针的作用,因为它可以延迟函数的执行,特别适合作为回调函数使用。它比普通函数更加的灵活和便利。

三、std::bind

       &emsp;&emsp;可将std::bind函数看作一个通用的函数适配器,它接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。

       &emsp;&emsp;std::bind将可调用对象与其参数一起进行绑定,cvv支付源码绑定后的结果可以使用std::function保存。

       std::bind主要有以下两个作用:

       将可调用对象和其参数绑定成一个仿函数;

       只绑定部分参数,减少可调用对象传入的参数。

std::bind绑定普通函数double?my_divide(double?x,?double?y)?{ ?return?x?/?y;?}void?func1(int?b,?char?a,?long?c,?int?d){ cout?<<?b?<<?"?"?<<?a?<<?"?"?<<?c?<<?"?"?<<?d?<<?"\n";}int?main(){ auto?fn_half?=?std::bind(my_divide,?std::placeholders::_1,?2);cout?<<?fn_half()?<<?"\n";?//输出结果:?5std::function<void(int,?long)>?func?=?std::bind(func1,?std::placeholders::_1,?'c',?std::placeholders::_2,?);//输出结果:?c??func(,?);return?0;}

       bind的第一个参数是函数名,普通函数做实参时,会隐式转换成函数指针。因此std::bind(my_divide,std::placeholders::_1,2)等价于std::bind(&my_divide,std::placeholders::_1,2)。

       std::placeholders::_1表示占位符,即对my_divide的第一个形参进行占位,将my_divide函数适配成一个形参的函数。

std::bind绑定一个成员函数struct?Foo{ void?PrintSum(int?n1,?int?n2){ cout?<<?n1?/?n2?<<?"\n";}int?data?=?;};int?main(){ Foo?foo;auto?f?=?std::bind(&Foo::PrintSum,?&foo,?,?std::placeholders::_1);//PrintSum的第二个参数占位f(5);?//输出结果:return?0;}

       bind绑定类成员函数时,第一个参数表示对象的成员函数的指针,第二个参数表示对象的地址。

       第一个参数必须显式的指定&Foo::PrintSum,因为编译器不会将对象的成员函数隐式转换成函数指针,所以必须在Foo::PrintSum前添加&。

       使用对象成员函数的指针时,必须要知道指针属于哪个对象,因此第二个参数为对象的地址&foo。

std::bind绑定一个引用参数

       &emsp;&emsp;==默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中==。但是,与lambda类似,有时对有些绑定的参数希望以引用的方式传递,或是要绑定参数的类型无法拷贝。如果需要bind使用引用的方式赋值,则需要配合std::ref。

void?print(int?&a,?int?&b){ a++;b++;cout?<<?"函数调用:a="?<<?a?<<?",b?="?<<?b?<<?"\n";}int?main(){ int?a?=?1;int?b?=?2;print(a,?b);auto?func2?=?std::bind(print,?a,?std::ref(b));cout?<<?"调用前:a?=?"?<<?a?<<?",b?="?<<?b?<<?"\n";func2();cout?<<?"调用后:a?=?"?<<?a?<<?",b?="?<<?b?<<?"\n";return?0;}

       &emsp;&emsp;调用的时候,尽管函数传入的方式都是引用,但是略有不同。参数a使用的是传统的方式,参数b采用的是std::ref的方式。输出结果进一步验证:==默认情况下,bind的那些不是占位符的参数被拷贝到bind返回的可调用对象中,即以拷贝的方式存入bind 的返回的可调用对象中。==

参考文章

       blogs.com/pandamohist/p/.html

       版权声明:本文为CSDN博主「ufgnix」的原创文章:\ 原文链接:(/qq/article/details/)

第六节 std::bind 绑定器

       std::bind 是 C++ 标准库中的一个强大工具,用于将可调用对象与其参数一起绑定,形成一个仿函数,便于稍后调用。它主要发挥两个关键作用:第一,将可调用对象与任意数量的参数绑定,形成一个仿函数;第二,将多参数可调用对象转为单参数可调用对象,仅绑定部分参数。

       实际应用中,使用 std::bind 的示例代码如下:

       通过 std::bind 的绑定功能,可以控制函数的执行结果,同时使用 auto fr 保存 std::bind 的返回结果,将其视为仿函数类型,直接赋值给 std::function 对象。

       使用占位符如 std::placeholders::_1,代表将在函数调用时被传入的第一个参数替代。这使得 std::bind 的使用非常灵活,不仅可以直接绑定所有参数,也能仅绑定部分参数。

       当仅绑定部分参数时,通过 std::placeholders 来确定空位参数属于调用时的第几个参数。随后的示例代码展示了 std::bind 的这些特性。

       fr 的类型为 std::function,通过使用 std::bind,可以将 A 类成员函数 output 的指针和 a 绑定,形成一个仿函数存储于 fr 中。接着,将 A 类成员 i_ 的指针和 a 绑定,返回结果存储于 std::function 中,以备后续修改访问该成员。

       通过 std::bind 和 std::function 的配合,所有可调用对象的操作方法实现了统一。接下来,将展示 std::bind 的几个实际使用案例。

       1. std::bind 的简化与增强:bind 函数简化并增强了 bind1st 和 bind2nd 的功能,提供了统一的实现方式,无需分别考虑使用 bind1st 还是 bind2nd,只需使用 bind 即可。

       2. 组合使用 bind 函数:bind 的强大之处还在于可以组合多个函数。以找出集合中大于5且小于的元素个数为例,首先使用 std::bind 实现判断是否大于5的功能闭包,然后实现判断是否小于的功能闭包,最后将两个闭包通过逻辑与结合,即可实现复合多个函数的功能。

从示例到源码深入了解std::ref

       在编程中,std::ref是C++标准库提供的一种实用工具,用于将变量转换为可引用的对象。本文将通过实例和源码解析,深入理解std::ref的工作原理。

       std::ref和std::cref的作用是生成一个std::reference_wrapper对象,它能够根据传入参数自动推导模板类型。通过这个工具,我们可以改变函数参数的传递方式,无论是引用还是值传递。

       首先,让我们通过一个自定义值传递函数模板call_by_value来理解。这个模板会将参数值复制传递给fn函数。当call_by_value使用std::ref时,外部变量不会因函数内部的操作而改变,因为传递的是值拷贝。实际例子中,输出证实了这一点。

       在实际编程中,如std::bind的使用,需要将引用类型参数作为引用传递,std::ref在此场合显得尤为重要。通过std::ref包装待柯里化的函数,可以实现引用的正确传递,但需要理解bind函数如何处理和存储参数值。

       std::bind内部会创建一个可调用对象,其中存储参数的值。然而,对于引用类型,值传递会导致无法修改外部变量。这时,std::ref就派上用场,它通过左值引用包装变量,确保在值传递过程中仍保持引用信息。

       下面以修改后的代码为例,使用std::ref包装参数。在call_by_value中,包装后的a可以成功修改,输出结果证明了引用的正确使用。同样的,std::bind示例中,通过std::ref包装a,函数调用后的变量值可以被正确修改。

       总结来说,std::ref是处理引用参数和值传递问题的关键工具,通过将其应用到合适的场景,可以确保函数内部对变量的修改能正确反映到外部。