C++ 包装器,看这一篇就够了
C++ 包装器
1 简介
包装器用于给其他编程接口提供更一致或更合适的接口。
模板bind可替代bind1st和bind2nd,且更灵活
模板mem_fn让您能够将成员函数作为常规函数进行传递
模板reference_wrapper让您能够创建像引用但可被复制的对象
包装器function让您能够以统一的方式处理多种类似于函数的形式
模板function是在头文件functional头文件中声明的,他从参数和返回值的角度定义了一个对象,可用于包装调用参数和返回值相同的函数指针、伪函数或lambda表达式
2 为什么使用包装器
由于函数调用可以使用函数名、函数指针、函数对象或有名称的lambda表达式,可调用类型太丰富导致模板的效率极低。
包装器用于解决效率低的问题。
3 测试与对比
3.1 普通版本与优化版本
3.1.1 代码
somedefs.h
#pragma once
// somedefs.h
#include <iostream>
template <typename T, typename F>
T use_f(T v, F f)
{
static int count = 0;
count++;
std::cout << " use_f count = " << count
<< ", &count = " << &count << std::endl;
return f(v);
}
class Fp
{
private:
double z_;
public:
Fp(double z = 1.0) : z_(z) {}
double operator()(double p) { return z_ * p; }
};
class Fq
{
private:
double z_;
public:
Fq(double z = 1.0) : z_(z) {}
double operator()(double q) { return z_ + q; }
};
main.cpp
/*
Project name : _2OWrappers
Last modified Date: 2022年5月6日10点09分
Last Version: V1.0
Descriptions: 包装器
*/
#include "somedefs.h"
#include <iostream>
#include <functional>
double dub(double x) { return 2.0 * x; }
double square(double x) { return x * x; }
int main()
{
using namespace std;
double y = 1.21;
//此处实例化了五个use_f模板函数,导致编译代码多,效率低
cout << "普通版本******************************************************" << endl;
cout << "Function pointer dub:\n";
cout << " " << use_f(y, dub) << endl;
cout << "Function pointer square:\n";
cout << " " << use_f(y, square) << endl;
cout << "Function object Fp:\n";
cout << " " << use_f(y, Fp(5.0)) << endl;
cout << "Function object Fq:\n";
cout << " " << use_f(y, Fq(5.0)) << endl;
cout << "Lambda expression 1:\n";
cout << " " << use_f(y, [](double u) {return u * u; }) << endl;
cout << "Lambda expression 2:\n";
cout << " " << use_f(y, [](double u) {return u + u / 2.0; }) << endl;
cout << "优化版本******************************************************" << endl;
//考虑到上述函数的参数和返回值(call signature)都为 double(double),
//因此使用function<double(double)>装饰它创建六个包装器,实现只实例化一个use_f函数模板
function<double(double)> ef1 = dub;
function<double(double)> ef2 = square;
function<double(double)> ef3 = Fq(10.0);
function<double(double)> ef4 = Fp(10.0);
function<double(double)> ef5 = [](double u) {return u * u; };
function<double(double)> ef6 = [](double u) {return u + u / 2.0; };
cout << "Function pointer dub:\n";
cout << " " << use_f(y, ef1) << endl;
cout << "Function pointer square:\n";
cout << " " << use_f(y, ef2) << endl;
cout << "Function object Fp:\n";
cout << " " << use_f(y, ef3) << endl;
cout << "Function object Fq:\n";
cout << " " << use_f(y, ef4) << endl;
cout << "Lambda expression 1:\n";
cout << " " << use_f(y, ef5) << endl;
cout << "Lambda expression 2:\n";
cout << " " << use_f(y, ef6) << endl;
return 0;
}
3.1.2 运行结果
普通版本******************************************************
Function pointer dub:
use_f count = 1, &count = 00007FF6DD7436D0
2.42
Function pointer square:
use_f count = 2, &count = 00007FF6DD7436D0
1.4641
Function object Fp:
use_f count = 1, &count = 00007FF6DD7436D4
6.05
Function object Fq:
use_f count = 1, &count = 00007FF6DD7436D8
6.21
Lambda expression 1:
use_f count = 1, &count = 00007FF6DD7436DC
1.4641
Lambda expression 2:
use_f count = 1, &count = 00007FF6DD7436E0
1.815
优化版本******************************************************
Function pointer dub:
use_f count = 1, &count = 00007FF6DD7436E8
2.42
Function pointer square:
use_f count = 2, &count = 00007FF6DD7436E8
1.4641
Function object Fp:
use_f count = 3, &count = 00007FF6DD7436E8
11.21
Function object Fq:
use_f count = 4, &count = 00007FF6DD7436E8
12.1
Lambda expression 1:
use_f count = 5, &count = 00007FF6DD7436E8
1.4641
Lambda expression 2:
use_f count = 6, &count = 00007FF6DD7436E8
1.815
D:\Prj\_C++Self\_34Wrappers\x64\Debug\_34Wrappers.exe (进程 1132)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
3.2 最优化版本
3.2.1 代码
somedefs.h
#pragma once
#include <iostream>
#include <functional>
//使用function模板
template <typename T>
T use_f(T v, std::function<T(T)> f)
{
static int count = 0;
count++;
std::cout << " use_f count = " << count
<< ", &count = " << &count << std::endl;
return f(v);
}
class Fp
{
private:
double z_;
public:
Fp(double z = 1.0) : z_(z) {}
double operator()(double p) { return z_ * p; }
};
class Fq
{
private:
double z_;
public:
Fq(double z = 1.0) : z_(z) {}
double operator()(double q) { return z_ + q; }
};
main.cpp
/*
Project name : _2OWrappers_optimization
Last modified Date: 2022年5月6日10点30分
Last Version: V1.0
Descriptions: 包装器最优化
*/
#include "somedefs.h"
double dub(double x) { return 2.0 * x; }
double square(double x) { return x * x; }
int main()
{
using namespace std;
double y = 1.21;
typedef function<double(double)> fdd; // simplify the type declaration
cout << "Function pointer dub:\n";
cout << use_f(y, fdd(dub)) << endl; // create and initialize object to dub
cout << "Function pointer square:\n";
cout << use_f(y, fdd(square)) << endl;
cout << "Function object Fp:\n";
cout << use_f(y, fdd(Fp(5.0))) << endl;
cout << "Function object Fq:\n";
cout << use_f(y, fdd(Fq(5.0))) << endl;
cout << "Lambda expression 1:\n";
cout << use_f(y, fdd([](double u) {return u * u; })) << endl;
cout << "Lambda expression 2:\n";
cout << use_f(y, fdd([](double u) {return u + u / 2.0; })) << endl;
return 0;
}
3.2.2 运行结果
Function pointer dub:
use_f count = 1, &count = 00007FF7172836D0
2.42
Function pointer square:
use_f count = 2, &count = 00007FF7172836D0
1.4641
Function object Fp:
use_f count = 3, &count = 00007FF7172836D0
6.05
Function object Fq:
use_f count = 4, &count = 00007FF7172836D0
6.21
Lambda expression 1:
use_f count = 5, &count = 00007FF7172836D0
1.4641
Lambda expression 2:
use_f count = 6, &count = 00007FF7172836D0
1.815
D:\Prj\_C++Self\_33Wrapper_optimization\x64\Debug\_33Wrapper_optimization.exe (进程 1036)已退出,代码为 0。
要在调试停止时自动关闭控制台,请启用“工具”->“选项”->“调试”->“调试停止时自动关闭控制台”。
按任意键关闭此窗口. . .
4 README
此为本人读C++ Primer总结的笔记,如有错误或知识缺口,请在评论区告知。如本文有在实践中帮到您,是本人的荣幸。
https://zhuanlan.zhihu.com/p/583655872
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」