【C++ Efficiency】lazy evaluation(缓式评估)的4种用途

2023-09-20 23:40:54

lazy evaluation(缓式评估)

以某种方式撰写你的classes,使它们延缓运算,直到那些运算结果刻不容缓被迫切需要为止。

lazy evaluation的4种用途

1. Reference Counting(引用计数)

class String{}; //string类
 
String s1 = "Hello";
String s2 = s1;

上述这种通过复制赋值会引起较大的成本代价,s2以s1为初值通常涉及到new操作符分配堆内存,需要调用strcpy函数复制s1的数据到s2的内存,这是eager evaluation(急式评估):只因string的复制赋值函数被调用。然而,此时s2并不需要还未被使用,不需要被赋予实际内容。

lazy evaluation做法:让s1和s2共享一个值

数据共享的唯一危机在于其中某个字符串被修改时发生:

s2.convertToUpperCase();
//该语句的话就必须将s2内容做副本给s2私人使用了

lazy evaluation:
在真正需要之前,不用着急复制出副本,尽量拖延;
只要可以就共享使用其它值。在某些领域,常有可能永远不用提供副本了。

2. 区分读和写

String s = "Homer's Iliad";   
...
cout << s[3];			  //调用operator[] 读取s[3]
s[3] = 'x';				  //调用operator[] 写入s[3]

上述语句中,对引用而来的字符串进行读取操作是无需什么代价的,但是写入操作,可能需要先做出一个副本。

困难在于:我们无法判断调用operator[]是读还是写。

运用lazy evaluation和proxy class,我们可以延缓决定是读还是写操作,直到能做出判断。

3. Lazy Fetching(缓式取出)

//假设程序使用了包含许多对象的大型对象
//为保持每次执行的一致性与连贯性,它们必须被存储于一个数据库里
//每一个对象都有唯一的标识符,用来从数据库里取回对象

class LargeObject
{
public:
	LargeObject(ObjectID id);    //从磁盘中回存对象
	const string& field1() const;
	int field2() const;
	double field3() const;
	double string& field4() const;
	double string& field5() const;
	...
};

//从磁盘中回存对象的成本:
void restoreAndProcessObject(ObjectID id)
{
	LargeObject object(id);
	...
}

// LargeObject体积很大,获取所有的数据成本非常大,而且并非所有数据都必要
void restoreAndProcessObject(ObjectID id)
{
	LargeObject object(id);
	if(object.field2() == 0)
		cout << "Object" << id << ":null field2.\n";
}
//其实仅需field2的值,所以获取其他字段的付出都是浪费

lazy evaluation做法:
当需要某个数据的时候,才从数据库中去读取,即“demand-paged”(按需分页)对象初始化的实现方法。

class LargeObject
{
public:
	LargeObject(ObjectID id); 
	const string& field1() const;
	int field2() const;
	double field3() const;
	double string& field4() const;
	double string& field5() const;
	...
 
private:
	ObjectID oid;
	
	//mutable表示在任何函数里它们都能被修改,甚至const成员函数
	mutable string* field1Value;   
	mutable int* field2Value;
	mutable double* field3Value;
	mutable string* field4Valuel
	...
};
 
LargeObject::LargeObject(ObjectID id)
	:oid(id),field1Value(0),field2Value(0),field3Value(0)...
	{}
	
const string& LargeObject::field1() const
{
	if(field1Value  == 0)
	{
		//从数据库中读取field1的值,使field1Value指向这个值
	}
	return *field1Value;
}
  • 对象中每个字段都用一个指向数据的指针来表示,LargeObject构造函数把每个指针初始化为null:null指针表示字段还没从数据库中读取数值;
  • 每个LargeObject成员函数在访问字段指针的所指向的数据之前必须检查字段指针的状态:如果为null,则对数据进行操作之前必须从数据库中读取对应的数据。

4. Lazy Expression Evaluation(表达式缓评估)

//数值应用
template<class T>	
class Matrix{...};			//homogeneous matrices(同质矩阵)
 
Matrix<int> m1(1000,1000);	//一个1000*1000的矩阵
Matrix<int> m2(1000,1000);
...
Matrix<int> m3 = m1 + m2;	

//+的实现是eagar evaluation:
//计算和返回m1 与 m2的和:大规模运算且大量分配内存

//lazy evaluation做法:
//建立一个数据结构于m3中,表示m3的值是m1和m2的和
Matrix<int> m4(1000,1000);
Matrix<int> m3 = m4*m1;

lazy evaluation可以避免非必要的数值计算动作。

总结

上述四种用途展示了lazy evaluation在许多领域的作用:可避免非必要的对象复制,可区别operator[ ]的读取与写入操作,可避免非必要的数据库读取操作,可避免非必要的数值计算动作。

但是,只有当“你的软件被要求执行某些计算,而那些计算其实可以避免”的情况下,lazy evaluation才有用处。

更多推荐

Docker compose

文章目录Dockercompose1.介绍2.为什么要DockerCompose3.DockerCompose文件(docker-compose.yml)imagecommandentrypointenvironmentnetworksvolumesportsexposedepends_onenv_file4.Dock

Java21的新特性

Java语言特性系列Java5的新特性Java6的新特性Java7的新特性Java8的新特性Java9的新特性Java10的新特性Java11的新特性Java12的新特性Java13的新特性Java14的新特性Java15的新特性Java16的新特性Java17的新特性Java18的新特性Java19的新特性Java2

STM32WB55开发(3)----断开蓝牙连接

STM32WB55开发----3.断开蓝牙连接概述硬件准备视频教学样品申请源码下载选择芯片型号配置时钟源配置时钟树RTC时钟配置查看开启STM32_WPAN条件配置HSEM配置IPCC配置RTC启动RF开启蓝牙LED配置设置工程信息工程文件设置参考文档SVCCTL_App_NotificationACI_HAL_GET

【C++】继承

文章目录一、继承的定义1.1继承的定义方式1.2继承关系与访问限定符二、基类和派生类对象赋值转换三、继承中的作用域四、派生类的默认成员函数五、继承和友元六、继承和静态成员六、多继承导致的菱形继承七、继承总结一、继承的定义继承(inheritance)机制是面向对象程序设计使代码可以复用的最重要的手段,它允许程序员在保持

ARM如何利用PMU的Cycle Counter(时钟周期)来计算出CPU的时钟频率

本章将学习如何利用ARMPMU的CycleCounter,来计算出CPU的时钟周期,从而计算出CPU的时钟频率。在介绍计算方法前,有必要先介绍下什么是时钟周期、机器周期以及指令周期。如何计算出CPU的时钟频率一,时钟周期,机器周期以及指令周期1.1时钟周期(clockcycle)以及时钟频率(clockfrequenc

SQL plus简单使用

查看Oracle数据库全部数据库数据库名称SELECTnameFROMv$database;这将返回所有数据库的名称。视图通过SQL查询dba_registry视图:另一个查看数据库的方法是查询dba_registry视图,该视图包含了数据库中安装的所有组件的信息。以下是示例SQL查询:SELECTcomp_nameF

我的git笔记

git加速https://ghproxy.com/https://github.com/cudpp/cudpp.gitgitclonehttps://ghproxy.com/https://github.com/triple-Mu/YOLOv8-TensorRT.git安装git#删除当前gitsudoapt-getr

002-第一代硬件系统架构确立及产品选型

第一代硬件系统架构确立及产品选型文章目录第一代硬件系统架构确立及产品选型项目介绍摘要硬件架构硬件结构选型及设计单片机选型上位机选型扯点别的关键字:Qt、Qml、信号采集机、数据处理、上位机项目介绍欢迎来到我们的QML&C++项目!这个项目结合了QML(QtMeta-ObjectLanguage)和C++的强大功能,旨在

clickhouse学习之路----clickhouse的特点及安装

clickhouse学习笔记反正都有学不完的技术,不如就学一学clickhouse吧文章目录clickhouse学习笔记clickhouse的特点1.列式存储2.DBMS的功能3.多样化引擎4.高吞吐写入能力5.数据分区与线程级并行clickhouse安装1.关闭防火墙2.CentOS取消打开文件数限制3.安装依赖4.

在SpringBoot中如何整合数据源?

在企业级应用开发中,数据存储是必不可少的一环。为了简化数据访问层的开发,SpringBoot提供了对多种数据源的整合支持。本文将介绍如何在SpringBoot项目中整合常见的数据源,包括JdbcTemplate、MyBatis和JPA,并探讨如何配置和使用多数据源。1.数据源的选择与配置1.1.常见的数据源类型在Jav

2020-2023中国高等级自动驾驶产业发展趋势研究-概念界定

1.1概念界定自动驾驶发展过程中,中国出现了诸多专注于研发L3级以上自动驾驶的公司,其在业界地位也越来越重要。本报告围绕“高等级自动驾驶”展开,并聚焦于该技术2020-2023年在中国市场的变化趋势进行研究。1.1.1什么是自动驾驶自动驾驶汽车[1]是指:搭载先进车载传感器、控制器、执行器等装置,并融合现代通信与网络技

热文推荐