跟我学c++高级篇——模板元编程之八惰性加载
一、Lazy evaluation
惰性加载或者延迟计算,在前面的文章《跟我学c++中级篇——迟延计算》中分析过。叫法怎么叫都可以,只要大家明白这个意思即可。Lazy evaluation一般可用于下面的情况:
1、模板中的对象非立刻的模板实例化,也就是说有的类很大,其实有些类在初始化并用不到,只有在实现具体功能时,才用得到。而如果恰好这些对象又比较耗资源,用到的可能性又不是多大时,惰性加载的优势便体现了出来。
2、函数功能的分发延迟,其实就是函数对象的延迟调用。
3、元编程或者模板编程的计算延迟,比如在求类似数列求和、递归计算等中都有体现。
内核中使用的COW这种技术,其实就可以认为是一种延迟加载。
二、作用
计算机技术发展到现在,本质上还是资源的抢夺,只要无法解决这个问题,各种资源管理技术仍然会不断出现。所以延迟加载带来的好处就是:
1、提高了性能,无论减少实例化还是在编译期实现计算都提高了程序的处理速度,提高了性能。
2、对计算机资源,特别是内存的耗用减少。
3、类似于函数编程,更容易进行并行计算处理。
4、有利用于在复杂情况下维护和异常分析,比如设计某些计算会在什么状态下才会启动,那么之前的异常分析中,就不用考虑这一部分了。
5、如《c++模板元编程》中提到的,减少编译时间,提供安全性,通过定义无效的计算而不去执行。
在c++中实现延迟加载可以使用下的几种方式:
1、前面提到过的增加一个外覆器,不对外暴露相关类型、结果等。模板就不会主动去实例化,从而达到延迟加载的目的。
2、使用一些基本的控制,比如把运行期的if条件语句转到编译期一些if_函数系列,则就可以导致惰性加载。
3、封装一些函数和运算子的对象化,这和1原理基本相同。
在实际编程可以经常用到的有c++11中的std::function, lambda表达式以及c++11和std::Optional等来实现。
三、例程
这里看一下相关的应用例程:
#include <iostream>
template<typename T, bool have>
struct Ex
{static T* getins(const T* ins){if (have){return ins->max();}else{return new T(* ins);}}
};struct NoMax
{NoMax() {}NoMax(const NoMax&) {}
};Ex<NoMax, false> instance; //lazy
int main()
{NoMax nm;//NoMax* newObject = instance.getins(&nm);//error
}
上面注释的代码就是想窥探模板实现的内部数据了,就报一个错误,否则只是给一个外部类的实现就不会有问题。再看一个函数延迟加载的:
#include <tuple>
#include <iostream>template <typename Func, typename... Args>
class LazyFunc
{
private:Func func;std::tuple<Args...> args;using invoke = std::invoke_result_t<Func, Args...>;public:LazyFunc(Func f, Args... a): func(f), args{ a... }{}operator invoke(){return std::apply(func, args);}
};
//定义推导规则 c++17以后可忽略
template <typename Func, typename... Args>
LazyFunc(Func, Args...)->LazyFunc<Func, Args...>;int Sub(int a, int b)
{std::cout << "start sub..." << std::endl;return a - b;
}int main()
{auto result = LazyFunc(Sub, 12, 11);std::cout << "go ......" << std::endl;std::cout << result << std::endl;return 0;
}
这其实就是使用c++新标准来实现的,为了让延迟加载更能体现的清晰,可以继续在上面封装,这样就容易理解延迟加载。有兴趣可以自己试试。
四、元编程中的应用
弄清楚了上面的原理,再看一下在元编程的应用:
#include <type_traits>
template<typename T>
struct HaveEx
{static T* getins(const T* ins){return instance->max();}
};template<typename T>
struct NoHaveEx
{static T* getins(const T* ins){return new T(* ins);}
};template<typename T,bool ok>
using CT = std::conditional<ok, HaveEx<T>, NoHaveEx<T>>::type ;
int main()
{ CT<NoMax, false> ct;NoMax * nn = ct.getins(&nm);std::cout << typeid(CT<NoMax,false>).name() << '\n';
}
多写代码,好多东西自然就明白了,慢慢来。
五、总结
惰性加载或者缓式应用,这种技术的目的是什么一定要掌握,明白了其为什么出现,比会用更好。学习一门技术的应用基本上难不到大多数人,但对大多数人来说,如何掌握这其中的内在原理并灵活应用到其它一些类似的方向上,这才是更上一层。世界这么大,技术是无穷的,但原理却要少得多。越往后学,大家会发现,初学计算机时的那些原理反而越深刻的影响到自己。
如果始终觉察不到这一点,那就只能是那就了。
相关文章:
跟我学c++高级篇——模板元编程之八惰性加载
一、Lazy evaluation 惰性加载或者延迟计算,在前面的文章《跟我学c中级篇——迟延计算》中分析过。叫法怎么叫都可以,只要大家明白这个意思即可。Lazy evaluation一般可用于下面的情况: 1、模板中的对象非立刻的模板实例化,也就是…...
【Python入门第二十二天】Python 类和对象
Python 类/对象 Python 是一种面向对象的编程语言。 Python 中的几乎所有东西都是对象,拥有属性和方法。 类(Class)类似对象构造函数,或者是用于创建对象的“蓝图”。 创建类 如需创建类,请使用 class 关键字&…...
qml的进度条
QML是一种用于创建动态用户界面的声明式语言,它支持使用JavaScript表达式来定义属性绑定和信号处理器。在本文中,我们将介绍如何使用JavaScript在QML中绘制一个进度条(ProgressBar),并设置其前景色和背景色。进度条是一…...
Pycharm补丁包使用教程
虽然社区版在大多情况下已经够用,但是有很多功能都是没有的,对照起一些教程之类的就很不方便 现在直接教一种简单中的简单的补丁包使用方法 我这里用的是 pycharm 19.2.6 注意右下角的configure 一般别的方法都是 打开,然后添加路径&#…...
用VAE生成图像
用VAE生成图像自编码器AE,auto-encoderVAE讲讲为什么是log_var为什么要用重参数化技巧用VAE生成图像变分自编码器是自编码器的改进版本,自编码器AE是一种无监督学习,但它无法产生新的内容,变分自编码器对其潜在空间进行拓展&#…...
你只会说MVC模型是什么但是不会实现?今天带你走通Web、Servlet、MVC、SpringMVC。代码演示很清晰
文章目录HTTP请求和HTTP响应从0手写一个Web服务器,看看能有多累人使用Servlet实现一个服务器,看看多简单Serlvet的创建Servlet的运行Servlet的其他问题Servlet这么爽,我们简单地探索一下它的原理JSP跟Servlet合作啦,我们来看一下他…...
C++中邻接矩阵、邻接表、链式前向星具体用法及讲解
图论在提高组中几乎占据半壁江山,而今天要讲的就是如何存储一个图一.邻接矩阵原理要建立一个图,根本的要素就是边和点而想要让计算机存储边和点就需要用到一些数据结构邻接矩阵是最简单的他使用了一个二维数组,来表示一个图假设数组名为map那…...
appium的安装详解
安装appium 爬虫手机APP需要实现自动化,所以要使用appnium来实现点击,输入,滑动等操作。由于appnium的安装较为繁琐,所以特意整理一篇文章来展示安装的详细过程过程中。 安装appnium共有3个步骤 安装 Android SDK安装 JDK安装 …...
STM32之 串口
串口通信串行接口简称串口,也称串行通信接口或串行通讯接口(通常指COM接口),是采用串行通信方 式的扩展接口。串行接口(Serial Interface)是指数据一位一位地顺序传送。其特点是通信线路简 单,只…...
CSDN 编程竞赛三十三期题解
竞赛总览 CSDN 编程竞赛三十三期题解:比赛详情 (csdn.net) 竞赛题解 题目1、奇偶排序 给定一个存放整数的数组,重新排列数组使得数组左边为奇数,右边为偶数(奇数和偶数的顺序根据输入的数字顺序排列)。 第七期竞赛…...
逆向练习之 mingyue.exe wp
目录 一.查壳 二.主函数 三.operate函数 四.storage函数及4618和4620指针功能的解释 五.judge函数 六.求解flag 七.其他--ida字符识别问题 一.查壳 64位无壳 二.主函数 1.这里的pointer_4618和4620是两个相邻的八字节内存单元,其中4620是字符串链表表头head 2.puts和s…...
LeetCode 热题 HOT 100 Java 题解 -- Part 3
练习地址 Part 1 : https://blog.csdn.net/qq_41080854/article/details/128829494 Part 2 : https://blog.csdn.net/qq_41080854/article/details/129278336 LeetCode 热题 HOT 100 Java 题解 -- Part 376. 最佳买卖股票时机含冷冻期77. 戳气球78. 零钱兑换79. 打家劫舍 III…...
QML键盘事件
在QML中,当有一个按键按下或释放时,会产生一个键盘事件,将其传递给获得有焦点的QML项目(讲focus属性设置为true,则获得焦点)。 按键处理的基本流程: Qt接收密钥操作并生成密钥事件。如果 QQuic…...
跨域问题怎么解决
解决跨域,原因:域名不同,域名相同端口不同;二级域名不同 什么是跨域? 就是两个项目之间通讯,如果访问的域名与ajax访问的地址不一致情况,默认情况浏览器有一个安全机制。 postman不一定能测试…...
微服务网关Gateway和Zuul的区别
spring-cloud-Gateway是spring-cloud的一个子项目。而zuul则是netflix公司的项目,只是spring将zuul集成在spring-cloud中使用而已。 因为zuul2.0连续跳票和zuul1的性能表现不是很理想,所以催生了spring团队开发了Gateway项目。 Zuul: 使用的…...
专访华西二院吴邦华:隐私计算+AI全栈技术,构筑智慧医院建设的坚实数据底座|爱分析访谈
从IT时代步入DT时代,医疗大数据成为智慧医院建设的重要驱动力。经过多年信息化系统建设,很多医院已经积累了大量的医疗数据资源,但由于各业务系统间数据孤岛化严重、系统架构落后、数据缺乏深度治理等问题存在,导致现有数据深度及…...
《C++ Primer Plus》第18章:探讨 C++ 新标准(6)
可变参数模板 可变参数模板(variadic template)让您能够创建这样的模板函数和模板类,即可接收可变数量的参数。这里介绍可变参数模板函数。例如,假设要编写一个函数,它可接受任意数量的参数,参数的类型只需…...
.Net Core中使用是SQL Server的邮件发送功能
.Net Core中使用是sqlserver的邮件发送功能准备需求启用SQL Server的电子邮件功能检查和测试在.net Core中调用在sqlsrver的管理中有一个数据库邮件功能,再此可以使用sqlserver来自动发送一些邮件,但是有一些需要插入附件的邮件则需要使用程序代码来解决,下面就是使用C#来调用s…...
Nginx优化服务和防盗链
Nginx优化服务和防盗链一、长连接1、修改主配置文件2、测试3、在主配置文件添加4、验证二、Nginx第三方模块1、开源的echo模块2、查看是否成功3、加echo模块步骤4、网页测试验证三、搭建虚拟主机1、编译安装好nginx后,对主配置文件进行修改2、创建文件3、验证四、防…...
B树与B+树
认识了解MySQL中的B树B树引出什么是B树什么是B树B树的优点B树引出 在MySQL中,如果我们设置了主键, 那么对于该列表中的数据就有了一个索引,插入表中数据的主键值不能重复,而且不能为空. 那当我们插入数据的时候, 它是如何通过索引来判断主键值是否重复的呢? 我们想到它肯定是…...
后进先出(LIFO)详解
LIFO 是 Last In, First Out 的缩写,中文译为后进先出。这是一种数据结构的工作原则,类似于一摞盘子或一叠书本: 最后放进去的元素最先出来 -想象往筒状容器里放盘子: (1)你放进的最后一个盘子(…...
python打卡day49
知识点回顾: 通道注意力模块复习空间注意力模块CBAM的定义 作业:尝试对今天的模型检查参数数目,并用tensorboard查看训练过程 import torch import torch.nn as nn# 定义通道注意力 class ChannelAttention(nn.Module):def __init__(self,…...
visual studio 2022更改主题为深色
visual studio 2022更改主题为深色 点击visual studio 上方的 工具-> 选项 在选项窗口中,选择 环境 -> 常规 ,将其中的颜色主题改成深色 点击确定,更改完成...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
【JVM】- 内存结构
引言 JVM:Java Virtual Machine 定义:Java虚拟机,Java二进制字节码的运行环境好处: 一次编写,到处运行自动内存管理,垃圾回收的功能数组下标越界检查(会抛异常,不会覆盖到其他代码…...
连锁超市冷库节能解决方案:如何实现超市降本增效
在连锁超市冷库运营中,高能耗、设备损耗快、人工管理低效等问题长期困扰企业。御控冷库节能解决方案通过智能控制化霜、按需化霜、实时监控、故障诊断、自动预警、远程控制开关六大核心技术,实现年省电费15%-60%,且不改动原有装备、安装快捷、…...
postgresql|数据库|只读用户的创建和删除(备忘)
CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
网站指纹识别
网站指纹识别 网站的最基本组成:服务器(操作系统)、中间件(web容器)、脚本语言、数据厍 为什么要了解这些?举个例子:发现了一个文件读取漏洞,我们需要读/etc/passwd,如…...
群晖NAS如何在虚拟机创建飞牛NAS
套件中心下载安装Virtual Machine Manager 创建虚拟机 配置虚拟机 飞牛官网下载 https://iso.liveupdate.fnnas.com/x86_64/trim/fnos-0.9.2-863.iso 群晖NAS如何在虚拟机创建飞牛NAS - 个人信息分享...
