5.程序转换语意学

目录

1.显示的初始化操作

2.参数的初始化

3.返回值的初始化

4.在使用者层面做优化

5.Copy Constructor要不要?


1.显示的初始化操作

已知有这样的定义:

X x0;

下面的三个定义,每一个都明显地以x0来初始化其class object;

void foo_bar()
{X x1(x0); //译注:定义了x1X x2 = x0; //译注:定义了x2X x3 = X(x0);//译注:定义了x3//...
}

必要的程序转化有两个阶段:
1)在C++中,“定义”是指“占用内存”的行为。上面的代码将会重写每一个定义,其中的初始化操作会被剥离。
2)Class 的copy constructor调用操作将会被安插进去。

举个例子,在明确上面的两种转换后,foo_bar()可能看起来像这样子:

//可能的程序转换
//C++伪代码
void foo_bar(){X x1;//译注:定义被重写,初始化操作被剥离X x2;//译注:定义被重写,初始化操作被剥离X x3;//译注:定义被重写,初始化操作被剥离//编译器安插X copy construction的调用操作x1.X::X(x0);x2.X::X(x0);x3.X::X(x0);//...
}

2.参数的初始化

把一个class object当作参数传给一个函数(或是作为一个函数的返回值),如下的代码要求局部的实例x0以memberwise的方式将xx当作初值。在编译器的实现技术上,有一种策略是导入临时性object,并调用copy constructor将它初始化,然后将此临时性object交给函数。

void foo(X x0);
X xx;
//...
foo(xx);

例如将前一段程序代码转换如下:

//C++伪代码
//编译器产生的临时对象
X __temp0;//编译器对copy constructor的调用
__temp0.X::X(xx);//重新改写函数调用操作,使用上述的临时对象
foo(__temp0);

然而这样做有个问题,问题在foo的声明上。foo()的声明必须被转换,形式参数必须从原来的一个class X object改变成一个class X reference,像这样子:

void foo(X &x0);

其中class X声明了一个destructor,它会在foo()函数完成之后被调用,对付那个临时性的object。

3.返回值的初始化

已知下面的这个函数定义:

X bar()
{X xx;// 处理 xx ...return xx;
}

你可能会问bar()的返回值如何从局部对象xx中拷贝过来?Stroustrup在cfont中的解决办法是一个双阶段转化:

首先加上一个额外参数,类型是class object的一个reference。这个参数用来放置被“copy constructed”而得的返回值。

然后在return 指令之前安插一个copy constructor的调用操作。

上述的代码转换,可能如下:

//函数转换
//以反映出copy constructor的应用
//C++伪代码
void bar(X &__result)
{X xx;//编译器所产生的default constructor调用操作xx.X::X();//......处理xx//编译器所产生的copy constructor调用操作__result.X::X(xx);return;
}

在举几个例子,例如: X xx = bar();将被转换成如下的两个指令语句。

X xx;
bar(xx);

如果程序声明了一个函数指针,像这样子:

X (*pf)();
pf = bar;

它也被转换成这样子。

void (*pf)(X &x);
pf = bar;

4.在使用者层面做优化

最先提出“程序员优化”的概念是Jonathan Shopiro,他定义了一个“计算用”的constructor。换句话说,程序员不再写:

X bar(const T &y,const T &z)
{X xx;//...以y和z来处理xxreturn xx;
}

那会要求xx被“memberwise”的拷贝到编译器产生的__result之中。Jonathan定义另外一个constructor,可以直接计算xx的值。

X bar(const T &y,const T &z)
{return X(y,z);
}

于是当bar()的定义被转换之后,效率会更加的高。

//C++伪代码
void 
bar(X &__result,const T &y,const T &z)
{__result.X::X(y,z);return;
}

__result被直接计算出来,而不是经过copy constructor拷贝得到的。

5.Copy Constructor要不要?

已知下面的3D坐标点类:

class Point3d
{
public:Point3d(float x,float y,float z);//...
private:float _x,_y,_z;
};

这个class的设计者需要提供一个explicit copy constructor吗?答案是no,三个坐标成员是以数值来存储的。bitwise copy既不会导致memory leak,也不会产address aliasing。它是最快速安全的。

实现copy constructor的最简单的方式是:

Point3d::Point3d(const Point3d &rhs)
{_x = rhs._x;_y = rhs._y;_z = rhs._z;
}

这没有问题,但使用C++ library的memcpy()会更有效率:

Point3d::Point3d(const Point3d &rhs)
{memcpy(this, &rhs, sizeof(Point3d));
}

然而不管使用memcpy()还是memset(),都只有在“class不含有任何由编译器产生的内部members”时才能有效的运行。如果Point3d class声明一个或一个以上的virtual functions,或内含一个virtual base class,那么使用上述的函数将会导致那些“被编译器产生的内部members”的初值改写。

如你所见,如果要正确使用memcpy()和memset(),则需要掌握某些C++ Object Model的语意学知识。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/53303.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

深度学习示例2-多输入多输出的神经网络模型

一、代码示例 from tensorflow import keras from tensorflow.keras import layers import numpy as np# 定义 多输入 多输出的模型 vocabulary_size = 1000 num_tags = 100 num_departments = 4title = keras.Input(shape=(vocabulary_size,), name = "title") tex…

kali——msfconsole的使用

目录 前言 msfconsole的使用基础 启动mfsconsole 各种辅助模块的使用 端口扫描模块(portscan) 查看端口扫描的模块 使用模块 查看所需设置 手动设置 执行 退出 各种漏洞模块的使用 nmap扫描主机漏洞 查看漏洞模块 使用漏洞模块 查看所需设…

Prometheus通过node_exporter监控Node节点,Node节点的详细指标解读

✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…

webpack基本使用(基础)

文章目录 概要理解 一、使用示例1.引入库2.创建config/webpack.dev.js 测试环境3.创建config/webpack.prod.js 正式环境3.创建eslintrc.js4.创建babel.config.js5.package.json 总结 概要理解 vue或者react 通常用webpack作为打包工具,打包成浏览器识别的html、css…

吴恩达深度学习笔记:卷积神经网络(Foundations of Convolutional Neural Networks)1.9-1.10

目录 第四门课 卷积神经网络(Convolutional Neural Networks)第一周 卷积神经网络(Foundations of Convolutional Neural Networks)1.9 池化层(Pooling layers)1.10 卷 积 神 经 网 络 示 例 ( …

Linux_kernel汇编驱动06

一、ARM汇编语言(GUN-gcc编译器下) 1、语句格式 {symbol} {instruction|directive|pseudo-instruction} { comment} symbol:为符号。 在ARM汇编语言中,符号必须从一行的行头开始,并且符号中不能包含空格。 在指令和伪指…

基于C++实现(MFC界面)家谱管理系统

一、题目:家谱管理系统 二、内容: 2.1 概述 2.1.1 选题原因 做此题的原因是因为可以比较方便的记录家族历代成员的情况与关系,能很好的保存家族每一代的信息,而不用人工纸质的方式来存取家谱,更便于人们保存和使用…

爬虫练习(js逆向解密)

目标 网站地址交易列表 - 福建省公共资源交易电子公共服务平台 (fj.gov.cn) 抓取内容如下: 分析 查找js代码 点击下一页翻页的时候,查看请求返回的数据,发现data数据是经过加密后得到的 通过全局搜索data,发现有两千多个结果,一个…

AI超强语音转文本SenseVoice,本地化部署教程!

文章目录 模型介绍SenseVoice在线预览链接本地化部署VsCode 远程连接 模型介绍 SenseVoice专注于高精度多语言语音识别、情感辨识和音频事件检测 多语言识别: 采用超过40万小时数据训练,支持超过50种语言,识别效果上优于Whisper模型。富文本…

【Kubernetes知识点问答题】Docker CE 部署

目录 1.ca-certificates, gnupg, lsb-release 三个包的解释。 2.docker-ce, docker-ce-cli, containerd.io, docker-compose-plugin 作用。 3.K8s 在 1.2 之后就不再支持 docker,请解释对错。 4.举例说明创建容器以及以交互方式访问容器的命令? 1.ca-…

跨境电商代购系统中前台基本功能介绍:帮助更快的了解跨境代购业务

前台多语言:可支持语言有中文(繁体)中文(简体)英文等。多语言使用百度翻译引擎接口实现,翻译效果与百度一致;网站语言分为两大块:1.系统后台有语言包可以编辑修改网站标题以及发布文…

WPS中JS宏使用说明(持续优化...)

前言 好久没发文章了,今天闲来无事发篇文章找找之前的码字感觉。 正文 最近在写教案,发现之前的技术又可以派上用场了。就是JS,全称JavaScript,这个语言太强大了,我发现WPS里的宏现在默认就是JS。功能选项如下图&…

MySQL数据库安装(详细)—>Mariadb的安装(day21)

该网盘链接有效期为7天,有需要评论区扣我: 通过网盘分享的文件:mariadb-10.3.7-winx64.msi 链接: https://pan.baidu.com/s/1-r_w3NuP8amhIEedmTkWsQ?pwd2ua7 提取码: 2ua7 1 双击打开安装软件 本次安装的是mariaDB,双击打开mar…

Java运行环境的下载、安装、配置与运行

一、实验目的及要求 目的:掌握如何下载java JDK软件包,如何设置Java程序的运行环境,如何编写与运行Java程序,了解Java概貌。 要求: 1、安装Java JDK软件包; 2、练习编写简单的Java Application程序并掌握…

vscode安装使用plantuml插件

使用 VSCode 插件 如果你在 Visual Studio Code 中使用 PlantUML 插件,你可以按照以下步骤生成图片: 安装 PlantUML 插件: 在 VSCode 的扩展市场中搜索并安装 PlantUML 插件。 配置插件: 打开设置,确保插件配置正确。…

OceanBase block_file与log过大 的问题

一、说明 block_file 是存放sstable的数据文件,由datafile_disk_percentage 参数与datafile_size参数决定,两个参数同时配置,以datafile_size为主。 datafile_disk_percentage 默认值是90 datafile_size 默认值是0M到正无穷 因为block_file 的…

Node.js发票查验接口示例、识别查验接口参数返回

财务、审计等经常与发票打交道的人员常常会遇到虚假发票、错票、重复报销等一系列问题。对于会计审计、代理记账、电子商务等发票查验量多的企业来说,成千上万张发票如果仅依赖于人工来进行核验,速度慢效率低,准确率也没保障,因此…

MySQL record

更改密码: alter user rootlocalhost identified with mysql_native_password by ‘123456’; 注意: 在命令行方式下,每条MySQL的命令都是以分号结尾的,如果不加分号,MySQL会继续等待用户输入命令,直到MyS…

kube-prometheus部署

一、自定义配置(二选一,不建议用这个) grafana-service.yml apiVersion: v1 kind: Service metadata:name: grafananamespace: kube-monitoringlabels:app: grafanacomponent: core spec:type: NodePortports:- port: 3000nodePort: 30011selector:app: grafanaco…

uniapp 懒加载、预加载、缓存机制深度解析

uniapp 懒加载、预加载、缓存机制深度解析 文章目录 uniapp 懒加载、预加载、缓存机制深度解析一、为什么要使用uniapp的懒加载、预加载和缓存机制二、如何使用uniapp的懒加载、预加载和缓存机制1. 懒加载2. 预加载3. 缓存机制 四、扩展与高级技巧1. 结合懒加载和预加载优化页面…