当前位置: 首页 > news >正文

跟我学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 惰性加载或者延迟计算&#xff0c;在前面的文章《跟我学c中级篇——迟延计算》中分析过。叫法怎么叫都可以&#xff0c;只要大家明白这个意思即可。Lazy evaluation一般可用于下面的情况&#xff1a; 1、模板中的对象非立刻的模板实例化&#xff0c;也就是…...

【Python入门第二十二天】Python 类和对象

Python 类/对象 Python 是一种面向对象的编程语言。 Python 中的几乎所有东西都是对象&#xff0c;拥有属性和方法。 类&#xff08;Class&#xff09;类似对象构造函数&#xff0c;或者是用于创建对象的“蓝图”。 创建类 如需创建类&#xff0c;请使用 class 关键字&…...

qml的进度条

QML是一种用于创建动态用户界面的声明式语言&#xff0c;它支持使用JavaScript表达式来定义属性绑定和信号处理器。在本文中&#xff0c;我们将介绍如何使用JavaScript在QML中绘制一个进度条&#xff08;ProgressBar&#xff09;&#xff0c;并设置其前景色和背景色。进度条是一…...

Pycharm补丁包使用教程

虽然社区版在大多情况下已经够用&#xff0c;但是有很多功能都是没有的&#xff0c;对照起一些教程之类的就很不方便 现在直接教一种简单中的简单的补丁包使用方法 我这里用的是 pycharm 19.2.6 注意右下角的configure 一般别的方法都是 打开&#xff0c;然后添加路径&#…...

用VAE生成图像

用VAE生成图像自编码器AE&#xff0c;auto-encoderVAE讲讲为什么是log_var为什么要用重参数化技巧用VAE生成图像变分自编码器是自编码器的改进版本&#xff0c;自编码器AE是一种无监督学习&#xff0c;但它无法产生新的内容&#xff0c;变分自编码器对其潜在空间进行拓展&#…...

你只会说MVC模型是什么但是不会实现?今天带你走通Web、Servlet、MVC、SpringMVC。代码演示很清晰

文章目录HTTP请求和HTTP响应从0手写一个Web服务器&#xff0c;看看能有多累人使用Servlet实现一个服务器&#xff0c;看看多简单Serlvet的创建Servlet的运行Servlet的其他问题Servlet这么爽&#xff0c;我们简单地探索一下它的原理JSP跟Servlet合作啦&#xff0c;我们来看一下他…...

C++中邻接矩阵、邻接表、链式前向星具体用法及讲解

图论在提高组中几乎占据半壁江山&#xff0c;而今天要讲的就是如何存储一个图一.邻接矩阵原理要建立一个图&#xff0c;根本的要素就是边和点而想要让计算机存储边和点就需要用到一些数据结构邻接矩阵是最简单的他使用了一个二维数组&#xff0c;来表示一个图假设数组名为map那…...

appium的安装详解

安装appium 爬虫手机APP需要实现自动化&#xff0c;所以要使用appnium来实现点击&#xff0c;输入&#xff0c;滑动等操作。由于appnium的安装较为繁琐&#xff0c;所以特意整理一篇文章来展示安装的详细过程过程中。 安装appnium共有3个步骤 安装 Android SDK安装 JDK安装 …...

STM32之 串口

串口通信串行接口简称串口&#xff0c;也称串行通信接口或串行通讯接口&#xff08;通常指COM接口&#xff09;&#xff0c;是采用串行通信方 式的扩展接口。串行接口&#xff08;Serial Interface&#xff09;是指数据一位一位地顺序传送。其特点是通信线路简 单&#xff0c;只…...

CSDN 编程竞赛三十三期题解

竞赛总览 CSDN 编程竞赛三十三期题解&#xff1a;比赛详情 (csdn.net) 竞赛题解 题目1、奇偶排序 给定一个存放整数的数组&#xff0c;重新排列数组使得数组左边为奇数&#xff0c;右边为偶数&#xff08;奇数和偶数的顺序根据输入的数字顺序排列&#xff09;。 第七期竞赛…...

逆向练习之 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中&#xff0c;当有一个按键按下或释放时&#xff0c;会产生一个键盘事件&#xff0c;将其传递给获得有焦点的QML项目&#xff08;讲focus属性设置为true&#xff0c;则获得焦点&#xff09;。 按键处理的基本流程&#xff1a; Qt接收密钥操作并生成密钥事件。如果 QQuic…...

跨域问题怎么解决

解决跨域&#xff0c;原因&#xff1a;域名不同&#xff0c;域名相同端口不同&#xff1b;二级域名不同 什么是跨域&#xff1f; 就是两个项目之间通讯&#xff0c;如果访问的域名与ajax访问的地址不一致情况&#xff0c;默认情况浏览器有一个安全机制。 postman不一定能测试…...

微服务网关Gateway和Zuul的区别

spring-cloud-Gateway是spring-cloud的一个子项目。而zuul则是netflix公司的项目&#xff0c;只是spring将zuul集成在spring-cloud中使用而已。 因为zuul2.0连续跳票和zuul1的性能表现不是很理想&#xff0c;所以催生了spring团队开发了Gateway项目。 Zuul&#xff1a; 使用的…...

专访华西二院吴邦华:隐私计算+AI全栈技术,构筑智慧医院建设的坚实数据底座|爱分析访谈

从IT时代步入DT时代&#xff0c;医疗大数据成为智慧医院建设的重要驱动力。经过多年信息化系统建设&#xff0c;很多医院已经积累了大量的医疗数据资源&#xff0c;但由于各业务系统间数据孤岛化严重、系统架构落后、数据缺乏深度治理等问题存在&#xff0c;导致现有数据深度及…...

《C++ Primer Plus》第18章:探讨 C++ 新标准(6)

可变参数模板 可变参数模板&#xff08;variadic template&#xff09;让您能够创建这样的模板函数和模板类&#xff0c;即可接收可变数量的参数。这里介绍可变参数模板函数。例如&#xff0c;假设要编写一个函数&#xff0c;它可接受任意数量的参数&#xff0c;参数的类型只需…...

.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后&#xff0c;对主配置文件进行修改2、创建文件3、验证四、防…...

B树与B+树

认识了解MySQL中的B树B树引出什么是B树什么是B树B树的优点B树引出 在MySQL中,如果我们设置了主键, 那么对于该列表中的数据就有了一个索引,插入表中数据的主键值不能重复,而且不能为空. 那当我们插入数据的时候, 它是如何通过索引来判断主键值是否重复的呢? 我们想到它肯定是…...

Java 语言特性(面试系列2)

一、SQL 基础 1. 复杂查询 &#xff08;1&#xff09;连接查询&#xff08;JOIN&#xff09; 内连接&#xff08;INNER JOIN&#xff09;&#xff1a;返回两表匹配的记录。 SELECT e.name, d.dept_name FROM employees e INNER JOIN departments d ON e.dept_id d.dept_id; 左…...

设计模式和设计原则回顾

设计模式和设计原则回顾 23种设计模式是设计原则的完美体现,设计原则设计原则是设计模式的理论基石, 设计模式 在经典的设计模式分类中(如《设计模式:可复用面向对象软件的基础》一书中),总共有23种设计模式,分为三大类: 一、创建型模式(5种) 1. 单例模式(Sing…...

Opencv中的addweighted函数

一.addweighted函数作用 addweighted&#xff08;&#xff09;是OpenCV库中用于图像处理的函数&#xff0c;主要功能是将两个输入图像&#xff08;尺寸和类型相同&#xff09;按照指定的权重进行加权叠加&#xff08;图像融合&#xff09;&#xff0c;并添加一个标量值&#x…...

【大模型RAG】Docker 一键部署 Milvus 完整攻略

本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装&#xff1b;只需暴露 19530&#xff08;gRPC&#xff09;与 9091&#xff08;HTTP/WebUI&#xff09;两个端口&#xff0c;即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...

在Ubuntu中设置开机自动运行(sudo)指令的指南

在Ubuntu系统中&#xff0c;有时需要在系统启动时自动执行某些命令&#xff0c;特别是需要 sudo权限的指令。为了实现这一功能&#xff0c;可以使用多种方法&#xff0c;包括编写Systemd服务、配置 rc.local文件或使用 cron任务计划。本文将详细介绍这些方法&#xff0c;并提供…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

蓝桥杯3498 01串的熵

问题描述 对于一个长度为 23333333的 01 串, 如果其信息熵为 11625907.5798&#xff0c; 且 0 出现次数比 1 少, 那么这个 01 串中 0 出现了多少次? #include<iostream> #include<cmath> using namespace std;int n 23333333;int main() {//枚举 0 出现的次数//因…...

Java线上CPU飙高问题排查全指南

一、引言 在Java应用的线上运行环境中&#xff0c;CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时&#xff0c;通常会导致应用响应缓慢&#xff0c;甚至服务不可用&#xff0c;严重影响用户体验和业务运行。因此&#xff0c;掌握一套科学有效的CPU飙高问题排查方法&…...

Reasoning over Uncertain Text by Generative Large Language Models

https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829https://ojs.aaai.org/index.php/AAAI/article/view/34674/36829 1. 概述 文本中的不确定性在许多语境中传达,从日常对话到特定领域的文档(例如医学文档)(Heritage 2013;Landmark、Gulbrandsen 和 Svenevei…...