MEC | 条款4 非必要不提供 default constructor

news2025/1/11 3:02:14

条款4 非必要不提供 default constructor

文章目录

  • 条款4 非必要不提供 default constructor
    • classes 必须有默认构造函数?
    • Example
      • 1. 产生数组
        • 解决方法
      • 2.不适用于 template-based container clases
      • 3.虚基函数
    • 探讨
      • >>>>> 欢迎关注公众号【三戒纪元】 <<<<<

classes 必须有默认构造函数?

当我们定义1个类,如果没有定义构造函数,C++会默认提供1个构造函数(Constructors),用来将对象初始化,因此,default constructors 的作用就是在没有外来信息的情况下将对象初始化。

但是有许多对象,如果没有外来信息,就没有办法执行1个完全的初始化动作:

  • 一个用来表现通信簿字段的class,如果没有获得外界指定的人名,产生出来的对象将毫无意义;
  • 某些公司里,所有仪器设备上都必须贴上1个识别号码,如果这个识别号码的类产生的对象没有供应适当的ID号码,将毫无意义。

一般来说,“合理地从无到有生成对象”的 classes,都应该内含 default constructors,而 “必须拥有某些外来信息才能生成对象”的 classes,则不必有 default constructor。

Example

针对公司仪器而设计的 classes,识别码是一定得有的 constructor 自变量:

class EquipmentPiece {
public:
	EquipmentPiece(int IDNumber);
	...
};

EquipmentPiece 缺乏 default constructor,运行时可能在3种情况下出现问题:

1. 产生数组

一般而言没有任何办法可以为数组中的对象指定 constructor 自变量,几乎不可能产生1个由 EquipmentPiece objects 构成的数组

EquipmentPiece pieces[10]; // 错误!无法调用 EquipmentPiece ctors.
EquipmentPiece *pieces = new EquipmentPiece【10】;// 错误!其他问题

解决方法

  • 使用 non-heap 数组
  int ID1, ID2, ID3, ..., ID10; // 变量,从来放置一起识别代码
  ...
  EquipmentPiece pieces[] = {
  	EquipmentPiece(ID1),
  	EquipmentPiece(ID2),
  	EquipmentPiece(ID3),
  	...,
  	EquipmentPiece(ID10),
  }

此法无法延伸至 heap 数组

  • 使用“指针数组”而非“对象数组”
  typedef	EquipmentPiece* PEP; // PEP 是个指向 EquipmentPiece 的指针
  
  PEP piece[10]; // good,不需要调用 ctor
  PEP *pieces = new PEP[10]; // good
  
  // 各指针指向不同的 EquipmentPiece object
  for (int i = 0; i < 10; ++i) {
  	piece[10] = new EquipmentPiece(ID Number);
  }

这种方法有2个缺点:

  • 必须记得将数组所指的所有对象删除,如果忘了就会导致资源泄露;
  • 需要的内存总量比较大,因为需要一些空间来存放指针,还需要一些空间放置EquipmentPiece objects

而过度使用内存这个问题可以避免,可以先为数组分配 raw memory,然后使用 placement new 在这块内存上构造 EquipmentPiece objects

  // 分配足够的 raw memory, 给1个预备容纳10个 EquipmentPiece objects 的数组使用。
  void *rawMemory = operator new[](10*sizeof(EquipmentPiece))// 让pieces 指向此块内存,使这块内存被当做1个 EquipmentPiece 数组
  EquipmentPiece *pieces = static_cast<EquipmentPiece*>(rawMemory);
  
  // 利用“placement new” 构造这块内存中的 EquipmentPiece objects
  for(int i = 0; i < 10; ++i) {
  	new (&pieces[i]) EquipmentPiece( ID Number );
  }

这里还是必须提供给 constructor 1个自变量,作为每个EquipmentPiece object 的初值。

这项技术允许在缺乏“default constructor”的情况下仍然能产生对象数组;并不意味着可以回避提供 constructor 自变量。

placement new 必须手动调用 destructors, 调用 operator delete[] 释放 raw memory:

  // 以构造顺序的相反顺序析构
  for(int i = 9; i >= 0; --i) {
  	pieces[i].~EquipmentPiece();
  }
  
  // 释放 raw memory
  operator delete[](raw memory);

2.不适用于 template-based container clases

对于 templates 而言,被实例化的“目标类型”必须得有1个defatut constructorus

template<class T>
class Array {
public:
	Array(int size);
	...
private:
	T *data;
}

template<class T>
Array<T>::Array(int size)
{
	data = new T(size); // 数组中的而每个元素都调用T::T()
	...
}

如果谨慎设计 template, 可以消除对default constructor 的需求,例如标准库中的 vector template 会产生出行为类似的“可扩展数组”的各种 classes,不要求其类型参数拥有一个 default constructor.

3.虚基函数

Virtual base classes 如果缺乏 default constructors,则 Virtual base classes constructors 的自变量必须由欲产生的对象的派生层次最深(most derived)的class 提供

一个缺乏 default constructors 的 virtual base class,要求其所有的 derived classes —— 不论距离多远 —— 都必须知道且了解其意义,并提供 virtual base class 的 constructors 自变量。

探讨

To be or not to be is a question

所以到底应不应该提供 default constructors?

如果允许 defatult constructor,那么 无法保证 EquipmentPiece object 的所有字段都有富有意义的初值。

大部分 member functions 必须检查 ID 是否存在,否则会出问题。通常这部分的策略不明朗。

添加毫无意义的 defatult constructor ,会影响 classes 的效率。如果 member functions 必须测试字段是否真被初始化了,其调用者必须为测试行为付出时间代价,并为测试代码付出空间代价,因为其可执行文件和程序库都变大了。

如果 class constructors 可以确保对象所有字段都会被正确初始化,上述成本都可以免除。如果无法保证,最好避免 default constructor 出现。


>>>>> 欢迎关注公众号【三戒纪元】 <<<<<

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

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

相关文章

CANoe自动化工程的搭建

基于XMLCAPL建立自动化工程 1、导入ini文件2、新建 Test Environment3、报告类型4、代码编写 1、导入ini文件 工程的配置的文件&#xff0c;配置DUT相关信息&#xff0c;具体视工程而编写内容。 2、新建 Test Environment 1、新建XML测试用例环境 2、导入XML测试用例文件 …

vulnhub靶机Deathnote

难度&#xff1a;easy 下载地址&#xff1a;https://download.vulnhub.com/deathnote/Deathnote.ova 主机发现 arp-scan -l 端口扫描 nmap --min-rate 10000 -p- 192.168.21.140 进一步查看目标的端口的服务和版本 nmap -sV -sT -O -p22,80 192.168.21.140 扫描端口的漏洞…

微服务实战项目-学成在线-项目优化(redis缓存优化)

微服务实战项目-学成在线-项目优化(redis缓存优化) 1 优化需求 视频播放页面用户未登录也可以访问&#xff0c;当用户观看试学课程时需要请求服务端查询数据&#xff0c;接口如下&#xff1a; 1、根据课程id查询课程信息。 2、根据文件id查询视频信息。 这些接口在用户未认…

Java面试——一分钟搞懂限流算法

为什么限流 运营网站&#xff0c;经常会遇到各种挑战&#xff1a;某黑客发起DoS攻击、网络爬虫网页抓取、商品秒杀活动、双十一与618等场景&#xff0c;会使流量突然激增&#xff0c;如果不限制流量的访问就会使系统宕机。 常见的限流算法 1.漏桶算法&#xff08; LEAKY BUC…

Eclipse-配置彩色输出打印

文章目录 前言配置下载查看是否安装 前言 这是一篇古老的文章&#xff0c;那个时候还在用Eclipse &#xff0c;现在已经换 IDEA 了… 这是一篇 2018 年的文章&#xff0c;我只是将文章从个人比较挪到了CSDN 中 配置 配置完然后下载下面插件即可生成彩色代码。 下载 ANSI …

Vue2-收集表单数据、过滤器、内置指令与自定义指令、Vue生命周期

&#x1f954;&#xff1a;我徒越万重山 千帆过 万木自逢春 更多Vue知识请点击——Vue.js VUE2-Day4 收集表单数据1、不同标签的value属性2、v-model的三个修饰符 过滤器内置指令与自定义指令1、内置指令2、自定义指令定义语法&#xff08;1&#xff09;函数式&#xff08;2&am…

VMware vCenter 6.5 断电后无法启动修复方案

目录 第1章 前言 第2章 问题现象 第3章 解决方案 第4章、Tips 第1章 前言 本文主要介绍VMware vcsa 6.5由于电源异常/存储异常之后无法启动&#xff0c;进入磁盘自检模式处理方法。&#xff08;最近遇到类似情况比较多&#xff0c;Citrix Xenserver也遇到了&#xff0c;后来…

rocketMq启动broker报错找不到或无法加载主类 Files\Java\jdk1.8.0_171\lib\dt.jar;C:\Program]

假如弹出提示框提示‘错误: 找不到或无法加载主类 xxxxxx’。 1.打开runbroker.cmd 将"%CLASSPATH%"加上英文双引号&#xff0c;切勿别加中文双引号 2.打开runserver.cmd 同理 将"%CLASSPATH%"加上英文双引号&#xff0c;切勿别加中文双引号 3.正常执行即…

【Linux】邮件服务器搭建 postfix+dovecot+mysql (终极版 超详细 亲测多遍无问题)

&#x1f341;博主简介 &#x1f3c5;云计算领域优质创作者   &#x1f3c5;华为云开发者社区专家博主   &#x1f3c5;阿里云开发者社区专家博主 &#x1f48a;交流社区&#xff1a;运维交流社区 欢迎大家的加入&#xff01; 文章目录 前言基础原理准备工作一 、安装关于权…

一.RocketMQ概念

RocketMQ概念 1.概念2.应用场景3.MQ的优点和缺点4.常见MQ对比 1.概念 MQ(Message Queue)&#xff0c;是一种提供消息队列服务的中间件&#xff0c;也称为消息中间件&#xff0c;是一套提供了消息生产、存储、消费全过程API的软件系统。 RocketMQ是阿里巴巴2016年MQ中间件&…

C++QT教程3——手册4.11.1自带教程(笔记)——创建一个QT快速应用

文章目录 创建一个QT快速应用创建项目创建主视图添加应用逻辑为视图添加动画素材文件 参考文章 创建一个QT快速应用 本教程使用内置的QML类型&#xff0c;介绍了Qt Quick的基本概念。有关可以选择的用户界面选项的更多信息&#xff0c;请参阅用户界面。 本教程描述了如何使用…

约束综合中的逻辑互斥时钟(Logically Exclusive Clocks)

注&#xff1a;本文翻译自Constraining Logically Exclusive Clocks in Synthesis 逻辑互斥时钟的定义 逻辑互斥时钟是指设计中活跃&#xff08;activate&#xff09;但不彼此影响的时钟。常见的情况是&#xff0c;两个时钟作为一个多路选择器的输入&#xff0c;并根据sel信号…

【人工智能前沿弄潮】——生成式AI系列:Diffusers应用 (2) 训练扩散模型(无条件图像生成)

无条件图像生成是扩散模型的一种流行应用&#xff0c;它生成的图像看起来像用于训练的数据集中的图像。与文本或图像到图像模型不同&#xff0c;无条件图像生成不依赖于任何文本或图像。它只生成与其训练数据分布相似的图像。通常&#xff0c;通过在特定数据集上微调预训练模型…

Idea报错:Cannot resolve symbol “springframework“以及各种依赖包

问题描述&#xff1a; Idea导入了maven项目之后出现报错Cannot resolve symbol “springframework” &#xff0c;识别不了这个标识或者找不到这个包&#xff0c;明明这些依赖和包都有就是出现报错&#xff0c;并且运行按钮变成灰色 解决办法&#xff1a; 其实这个原因大概率就…

React构建的JS优化思路

背景 之前个人博客搭建时&#xff0c;发现页面加载要5s才能完成并显示 问题 React生成的JS有1.4M&#xff0c;对于个人博客服务器的带宽来说&#xff0c;压力较大&#xff0c;因此耗费了5S的时间 优化思路 解决React生成的JS大小&#xff0c;因为我用的是react-router-dom…

从源码Debug深入spring事件机制,基于观察者模式仿写spring事件监听骨架

文章目录 1.测试案例2.DEBUG源码分析3. 异步监听4.ApplicationListener子接口5. 注解支持6. 基于观察者模式高仿spring事件监听6.1 先定义自定义一个事件6.2 定义两个监听器6.3 定义一个持有所有监听器的对象&#xff0c;类似spring的SimpleApplicationEventMulticaster6.4 事件…

全面解析 Axios 请求库的基本使用方法

Axios 是一个流行的基于 Promise 的 HTTP 请求库&#xff0c;用于在浏览器和 Node.js 中进行 HTTP 请求。它提供了简单易用的 API&#xff0c;可以发送各种类型的请求&#xff08;如 GET、POST、PUT、DELETE等&#xff09;&#xff0c;并处理响应数据&#xff0c;Axios 在前端工…

Java——线程睡眠全方位解析

线程睡眠的方法&#xff1a; 在 Java 中&#xff0c;让线程休眠的方法有很多&#xff0c;这些方法大致可以分为两类&#xff0c;一类是设置时间&#xff0c;在一段时间后自动唤醒&#xff0c;而另一个类是提供了一对休眠和唤醒的方法&#xff0c;在线程休眠之后&#xff0c;可…

七牛云如何绑定自定义域名-小白操作说明——七牛云对象储存kodo

七牛云如何绑定自定义域名 **温馨提示&#xff1a;使用加速cdn自定义域名是必须要https的&#xff0c;也就是必须ssl证书&#xff0c;否则类似视频mp4 之类会无法使用。 ​ 编辑切换为居中 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 点击首页——…

Android12之MediaCodec用法套路(三十四)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…