【C++】C++11 篇三
·
【C++】C++11 篇三
function包装器
- std::function在头文件
- 类模板原型如下
// ,"只声明不定义" 的方式,强制用户必须使用它的特定偏特化版本,避免误用
template <class T> function; //undefined
////这是std::function的偏特化版本,也是实际被使用的版本
**template <class Ret, class... Args>**
**class function<Ret(Args...)>;**
模板参数说明:
Ret: 被调用函数的返回类型
Args…:被调用函数的形参
包装器的使用
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include <functional>
int f(int a, int b)
{
return a + b;
}
struct Functor
{
public:
int operator() (int a, int b)
{
return a + b;
}
};
class Plus
{
public:
static int plusi(int a, int b)
{
return a + b;
}
double plusd(double a, double b)
{
return a + b;
}
};
int main()
{
// 函数名(函数指针)
//f是普通函数名,在赋值时会隐式转换为函数指针(类型为int(*)(int, int))
std::function<int(int, int)> func1 = f;
//td::function内部会转发调用到函数f,本质是通过函数指针调用函数
cout << func1(1, 2) << endl;
// 函数对象
std::function<int(int, int)> func2 = Functor();
//调用func2(1, 2)时,std::function会调用存储的Functor对象的operator(),即执行Functor::operator()(1, 2)。
cout << func2(1, 2) << endl;
// lamber表达式
//编译器自动转换为一个匿名的函数对象(称为 "闭包类型"),该类型同样重载了operator()
std::function<int(int, int)> func3 = [](const int a, const int b){return a + b; };
//实际是调用这个匿名函数对象的operator(),执行 Lambda 体内的逻辑。
cout << func3(1, 2) << endl;
// 类的静态成员函数
//静态成员函数plusi属于类本身,而非对象,调用时不需要this指针
//绑定静态成员函数时必须加&(取地址),因为Plus::plusi本身不会隐式转换为函数指针
std::function<int(int, int)> func4 = &Plus::plusi;
cout << func4(1, 2) << endl;
//类的非静态成员函数
// 函数签名(返回类型 + 参数列表)
//非静态成员函数plusd隐含一个this指针参数(指向调用它的对象),因此其实际签名是double(Plus*, double, double)(第一个参数为this指针)。
std::function<double(Plus, double, double)> func5 = &Plus::plusd;
//调用func5时,第一个参数Plus()是临时对象,std::function会将其转换为this指针,再调用plusd(1.1, 2.2)。
cout << func5(Plus(), 1.1, 2.2) << endl;
return 0;
}
包装器,解决模板的效率低下,实例化多份的问题
- 模板工作原理:为每一种具体类型生成独立的代码实例
- 包装器的使用:避免了模板因多类型实例化导致的代码膨胀(冗余),和接口冗余
未使用包装器,由运行结果可见三次count值都为1,代码实例化了三份
#include<iostream>
#include <functional>
#include <vector>
using namespace std;
template<class F, class T>
T useF(F f, T x)
{
static int count = 0;
cout << "count:" << ++count << endl;
cout << "count:" << &count << endl;
return f(x);
}
double f(double i)
{
return i / 2;
}
struct Functor
{
double operator()(double d)
{
return d / 3;
}
int a = 10;
};
int main()
{
// 函数名
cout << useF(f, 11.11) << endl;//函数名会被隐式转换为函数指针double(*)(double)
// 函数对象
//模板推导时,F被推导为Functor类型
cout << useF(Functor(), 11.11) << endl;
// lamber表达式
cout << useF([](double d){ return d / 4; }, 11.11) << endl;
//vector里也可放
vector<function<double(double)>> v = { f, [](double d)->double { return d / 4; }, Functor() };
return 0;
}

- vector<function<double(double)>> v = { f, [](double d)->double { return d / 4; }, Functor() };

使用包装器后,count的值由1到3,足以证明代码就实例化了一份
int main()
{
//函数名
std::function<double(double)> func1 = f;
cout << useF(func1, 11.11) << endl;
//函数对象
std::function<double(double)> func2 = Functor();
cout << useF(func2, 11.11) << endl;
//lamber表达式
std::function<double(double)> func3 = [](double d)->double { return d / 4; };
cout << useF(func3, 11.11) << endl;
return 0;
}

bind
bind的使用 : 实现参数顺序调整
接受一个可调用对象,生成一个新的可调用对象来“适应”原对象的参数列表。
调用bind的一般形式:auto newCallable = bind(callable,arg_list);
newCallable本身是一个可调用对象,arg_list是一个逗号分隔的参数列表,对应给定的
callable的参数。当我们调用newCallable时,newCallable会调用callable,并传给它arg_list中
的参数。
#include<iostream>
#include <functional>
using namespace std;
int Sub(int a, int b)
{
return a - b;
}
double Plus(int a, int b, double rate)
{
return (a + b) * rate;
}
double PPlus(int a, double rate, int b)
{
return rate * (a + b);
}
class SubType
{
public:
static int sub(int a, int b)
{
return a - b;
}
int ssub(int a, int b, int rate)
{
return (a - b) * rate;
}
};
int main()
{
//Sub全局作用域
function<int(int, int)> rSub1 = bind(Sub, placeholders::_2, placeholders::_1);
auto rSub2 = bind(Sub, placeholders::_2, placeholders::_1);
cout << rSub1(10, 5) << endl;
cout << rSub2(10, 5) << endl << endl;
//Plus全局作用域
function<double(int, int)> Plus1 = bind(Plus, placeholders::_1, placeholders::_2, 4.0);
function<double(int, int)> Plus2 = bind(Plus, placeholders::_1, placeholders::_2, 4.2);
function<double(int, int)> Plus3 = bind(Plus, placeholders::_1, placeholders::_2, 4.4);
cout << Plus1(5, 3) << endl;
cout << Plus2(5, 3) << endl;
cout << Plus3(5, 3) << endl << endl;
// double PPlus(int a, double rate, int b)
//PPlus全局作用域,传实参不计数
function<double(int, int)> PPlus1 = bind(PPlus, placeholders::_1, 4.0, placeholders::_2);
function<double(int, int)> PPlus2 = bind(PPlus, placeholders::_1, 4.2, placeholders::_2);
cout << PPlus1(5, 3) << endl;
cout << PPlus2(5, 3) << endl << endl;
//sub为SubType局部静态作用域
function<double(int, int)> Sub1 = bind(&SubType::sub, placeholders::_1, placeholders::_2);
//ssub为SubType局部非静态作用域
SubType st;
function<double(int, int)> Sub2 = bind(&SubType::ssub, &st, placeholders::_1, placeholders::_2, 3);
cout << Sub1(1, 2) << endl;
cout << Sub2(1, 2) << endl << endl;
function<double(int, int)> Sub3 = bind(&SubType::ssub, SubType(), placeholders::_1, placeholders::_2, 3);
cout << Sub3(1, 2) << endl;
cout << typeid(Sub3).name() << endl;
return 0;
}
更多推荐
所有评论(0)