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

第十九章:特殊工具与技术

第十九章:特殊工具与技术

对于很多程序员来说,他们很少会用到本章的介绍的内容。

一.控制内存分配

我们能够重载new和delete,但其实不是对new和delete的重载,只是对new和delete操作符后面的函数进行重载。

当我们使用一条new表达式的时候,第一步new表达式调用一个名为operator new或operator new [] 的函数分配内存空间。第二步,编译器运行构造函数构造对象并传入初始值,第三步,返回一个指向该对象的指针。

当我们使用一条delete表达式的时候,第一步执行析构函数,第二步调用operator delete或operator delete []释放内存空间。

如果希望控制内存分配的过程,可以定义自己的operator new函数和operator delete函数。可以在全局作用域中定义这两个函数,也可以定义为成员函数。当编译器发现一条new或delete表达式时且对象是类类型,则先在类和基类的作用域中找这两个函数。当我们定义为成员函数时,这两类函数是隐式静态的。因为operator new用在对象构造之前,operator delete用在对象析构之后,所以必须是静态的且不能使用类的任何数据成员。

要实现这两类函数,可以使用malloc和free。

二.运行时内存识别

运行时内存识别的功能由两个运算符实现:typeid:用于返回表达式的类型;dynamic_cast:用于将基类的指针或引用安全的转换成派生类的指针或引用。

RTTI可以让我们在不能使用虚函数的情况下实现多态。

typeid操作的结果是一个常量对象的引用,该对象的类型是标准库类型type_info或type_info的公有派生类型。

当typeid作用于指针时(而非指针所指的对象),返回的结果是该指针的静态编译类型。

如果表达式的动态类型和静态类型不同,typeid会在运行时对表达式求值以确定返回的类型。

三.枚举类型

枚举类型使我们可以将一组整形常量组织在一起。每个枚举类型定义了一种新的类型,枚举属于字面值常量类型。

C++包含两种枚举:限定作用域和不限定作用域的。限定作用域是C++11新标准引入的,定义方式为在定义的时候在enum后面加上class或struct。

在限定作用域的枚举类型中,枚举成员的名字遵循常规的作用域准则,并且在枚举类型的作用域外是不可访问的(可以用作用域运算符访问);在不限定作用域的枚举类型中,枚举成员的作用域与枚举类型本身的作用域相同。

默认情况下,枚举值从0开始,依次加1,不过我们也能为一个或几个枚举成员指定专门的值。枚举值不一定唯一。枚举成员是const的。

enum是由某种整型类型表示的,在C++11新标准中,我们可以在enum的名字后加上冒号以及我们想在该enum中使用的类型。如果不加,限定的默认是int,非限定的默认不知。

四.类成员指针

成员指针是指可以指向类的非静态成员的指针。一般情况下指针指向一个对象,但是成员指针指向的是类的成员,而不是某个特定对象。

成员指针的类型囊括了类的类型及成员的类型。当初始化一个这样的指针时,我们令其指向类的某个成员,但是不指定该成员所属的对象;直到使用成员指针时,才提供成员所属的对象。

常规的访问控制规则对成员指针同样有效。

五.嵌套类

一个类可以定义在另一个类的内部,前者称为嵌套类或嵌套类型。

嵌套类和外部类没有什么特别的关系,只是嵌套类位于外部类的作用域中,受外部类的访问控制,两者都不含对方的成员。

六.union:一种节省空间的类

联合(union)是一种特殊的类。可以有多个数据成员,但是在任意时刻只有一个数据成员可以有值。分配给一个union对象的存储空间至少要能容纳它的最大成员。union可以为其成员指定public,protected和private等标记,默认为public。可以定义包括构造函数和析构函数在内的成员函数,不能定义虚函数。

匿名union是一个未命名的union,并且在右花括号和分号之间没有任何生命。一旦我们定义了一个匿名union,编译器就会自动为该union生成一个未命名的对象,在匿名union所在的作用域内该union的成员都是可以直接访问的。

对于union来说,要想构造或销毁类类型的成员必须执行非常复杂的操作,因此我们通常把含有类类型成员的union内嵌在另一个类中。这个类可以管理并控制与union的类类型成员有关的状态转换。

七.局部类

类可以定义在函数的内部,我们称这样的类为局部类。局部类定义的类型只在定义它的作用域可见。局部类的所有成员(函数在内)都必须完成定义在类的内部。局部类不允许声明静态成员。

局部类只能访问外层作用域定义的类型名、静态变量以及枚举成员。

八.固有的不可移植的特性

为了支持低层编程,C++定义了一些固有的不可移植的特性。所谓不可移植是指因机器而异。

类可以将其非静态成员定义为位域,在一个位域中含有一定数量的二进制位。当一个程序需要向其他程序或硬件设备传递而二进制数据时,通常会用到位域。

位域在内存中的布局是与机器相关的。

位域的类型必须是整型或枚举类型。通常是无符号类型。位域的声明形式是在成员名字之后紧跟一个冒号以及一个常量表达式,该表达式用于指定成员所占的二进制位数。

取地址运算符不能作用于位域,因此任何指针都无法指向类的位域。

当对象的值可能在程序的控制或检测之外被改变时,应该将该对象声明为volatile。关键字volatile告诉编译器不应对这样的对象进行优化。

volatile的确切含义与机器有关,只能通过阅读编译器文档来理解。

就像一个类可以定义const成员函数一样,它也能将成员函数定义为volatile的。只能volatile的成员函数才能被volatile的对象调用。

和const一样,我们只能将一个volatile对象的地址赋给一个指向volatile的指针。对引用也一样。

我们不能使用合成的拷贝/移动函数及赋值运算符初始化volatile。

C++使用链接指示指出任意非C++函数所用的语言。

对于使用链接指示定义的函数来说,它的每个声明都必须使用相同的链接指示,指向其他语言编写的函数的指针必须与函数本身使用相同的链接指示。

指向C函数的指针和指向C++函数的指针是不一样的类型,不能混用。

当我们使用链接指示时,它不仅对函数有效,而且对作为返回类型或形参类型的函数指针也有效(即若它的形参或返回类型是函数指针的话,则也是那种语言的函数指针)。所以如果我们希望给C++函数传入一个指向C函数的指针,则必须使用类型别名。

有时需要在C和C++中编译同一个源文件,为了实现这一目的,在编译C++版本的程序时预处理器定义__cplusplus。利用这个变量,我们可以在编译C++程序的时候有条件地包含进来一些代码。

完结撒花!!!🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉🎉

http://www.lryc.cn/news/280068.html

相关文章:

  • 大数据深度学习卷积神经网络CNN:CNN结构、训练与优化一文全解
  • RabbitMQ(九)死信队列
  • KEI5许可证没到期,编译却出现Error: C9555E: Failed to check out a license.问题解决
  • 南京观海微电子----时序图绘制工具
  • Gin CORS 跨域请求资源共享与中间件
  • TS:.d.ts 文件 和 declare 的作用
  • JavaScript-jQuery2-笔记
  • 设计模式之多线程版本的if------Balking模式
  • mybatis核心配置文件介绍
  • Linux完全卸载Anaconda3和MiniConda3
  • Apache Answer,最好的开源问答系统
  • 【C】内存分配
  • MySQL 从零开始:03 基本入门语句
  • 井盖异动传感器,守护脚下安全
  • 复合机器人作为一种新型的智能制造装备高效、精准和灵活的生产方式
  • 重置 Docker 中 Gitlab 的账号密码
  • 任务类型划分
  • docker搭建部署mysql并挂载指定目录
  • 即将推出的 OpenWrt One/AP-24.XY:OpenWrt 和 Banana Pi 合作路由器板
  • 【uniapp-小程序-分享图5/4】
  • 【响应式编程】前置知识和相关技术的总结
  • K8S--安装MySQL8(单机)
  • CMake+QT+大漠插件的桌面应用开发
  • OpenCV-24双边滤波
  • AI智能分析网关V4:太阳能+4G智慧水库远程可视化智能监管方案
  • 第8章-第8节-Java中的文件类File的简单介绍
  • CTF-PWN-沙箱逃脱-【seccomp和prtcl-2】
  • 【Docker篇】使用Docker操作镜像
  • css宽度适应内容
  • 粒子物理和原子核物理的理论在模拟和分析电路中的粒子束和辐射效应中的应用