C++学习笔记----7、使用类与对象获得高性能(二)---- 理解对象生命周期(5)

news2024/9/25 1:11:51

8、初始化器列表构造函数

        初始化器列表构造函数是一个带有std::initializer_list<T>作为第一个参数并且 没有任何其他参数或者有另外参数但是有缺省值的构造函数。initializer_list<T>类模板在<initializer_list>中定义。下面的类演示了其用法。该类只接收一个带有偶数个元素的initializer_list<double>;否则就抛出例外。

class EvenSequence
{
public:
	EvenSequence(initializer_list<double> values)
	{
		if (values.size() % 2 != 0) {
			throw invalid_argument{ "initializer_list should "
				"contain even number of elements." };
		}

		m_sequence.reserve(values.size());
		for (const auto& value : values) {
			m_sequence.push_back(value);
		}
		
		// Or:
		// m_sequence.assign(values);
	}

	void print() const
	{
		for (const auto& value : m_sequence) {
			std::print("{}, ", value);
		}
		println("");
	}
private:
	vector<double> m_sequence;
};

        在初始化器构造函数中可以使用基于范围的for循环来访问初始化器列表的元素,使用size()成员函数获得初始化器列表的元素数量。

        EvenSequence初始化器列表构造函数使用基于范围的for循环从给定的initializer_list<T>中拷贝元素。也可以使用vector的assign()成员函数。vector的不同的成员函数,包括assign(),我们会在以后详细讨论,作为简单的介绍,只是给出vector的一个概况,下面是使用assign()的初始化器列表构造函数的例子:

EvenSequence(initializer_list<double> values)
{
	if (values.size() % 2 != 0) {
		throw invalid_argument{ "initializer_list should "
			"contain even number of elements." };
	}

	m_sequence.assign(values);
}

EvenSequence对象可以构造如下:

	try {
		EvenSequence p1{ 1.0, 2.0, 3.0, 4.0, 5.0, 6.0 };
		p1.print();

		EvenSequence p2 { 1.0, 2.0, 3.0 };
	} catch (const invalid_argument& e) {
		println("{}", e.what());
	}

        p2的构造会抛出例外,因为在初始化器列表中含有奇数个元素。

        标准库有对初始化器列表构造函数的全部支持。例如,std::vector容器可以用初始化器列表进行初始化:

vector<string> myVec { "String 1", "String 2", "String 3" };

        如果没有初始化器列表构造函数,初始化这个vector的一个方法就是使用push_back()调用:

vector<string> myVec;
myVec.push_back("String 1");
myVec.push_back("String 2");
myVec.push_back("String 3");

        初始化器列表不限于构造函数,也可以用于正常的函数。

        注意:当类不仅拥有初始化器列表构造函数,还具有另一个单个参数的构造函数时,就要注意去调用正确的那一个了。例如,std::vector有初始化器列表构造函数来初始化一个带有给定元素集的vector。它也具有一个可以接收一个单独参数的构造函数,想要大小的新的vector。调用初始化器列表构造函数是使用大括号的初始化器,{},而调用另外的单独参数的构造函数是使用括号,()。例如:

vector<int> v1 { 6 }; // Constructs a vector with a single element, 6.
vector<int> v2 ( 6 ); // Constructs a vector with 6 default-
// initialized elements.

9、代理构造函数

        代理构造函数允许构造函数调用同一个类中的另一个构造函数。然而,该调用不能放到构造函数体内;一定要在构造函数初始化器中,必须是列表中唯一的成员初始化器。如下示例:

SpreadsheetCell::SpreadsheetCell(string_view initialValue)
: SpreadsheetCell { stringToDouble(initialValue) }
{
}

        当string_view构造函数(代理构造函数)被调用时,首先代理调用目标构造函数,本例中为参数为double的构造函数。当目标构造函数返回时,代理构造函数体被执行。

        在使用代理构造函数时,要确信避免出现构造函数递归,下面是一个例子:

class MyClass
{
    MyClass(char c) : MyClass { 1.2 } { }
    MyClass(double d) : MyClass { 'm' } { }
};

        第一个构造函数代理向第二个构造函数,而第二个又代理回第一个。这种代码的行为没有定义,依赖于编译器,会出现完全不可预知的结果。

10、构造函数转化与显式构造函数

        目前SpreadsheetCell的构造函数集如下:

export class SpreadsheetCell
{
public:
    SpreadsheetCell() = default;
    SpreadsheetCell(double initialValue);
    SpreadsheetCell(std::string_view initialValue);
    SpreadsheetCell(const SpreadsheetCell& src);
    // Remainder omitted for brevity
};

        单个参数的double与string_view构造函数可以用于将double或者string_view的对象转化为SpreadsheetCell。这样的构造函数叫做转化构造函数。编译器可以用这样的构造函数来执行隐式地转化。示例如下:

SpreadsheetCell myCell { 4 };
myCell = 5;
myCell = "6"sv; // A string_view literal

        其行为可能不总是你想要的。可以阻止编译器进行这样的转化,要通过标志构造函数为explicit。explicit关键字只在类定义中出现,示例如下:

export class SpreadsheetCell
{
public:
    SpreadsheetCell() = default;
    SpreadsheetCell(double initialValue);
    explicit SpreadsheetCell(std::string_view initialValue);
    SpreadsheetCell(const SpreadsheetCell& src);
    // Remainder omitted for brevity
};

        这样改了之后,下面这一行就不会编译成功:

myCell = "6"sv; // A string_view literal (see Chapter 2).

        在c++11之前,转化构造函数可以只有一个参数,如SpreadsheetCell例子中所示。从c++11开始,因为支持了列表初始化,转化构造函数可以有多个参数。我们看一个例子。假设你有如下的类:

class MyClass
{
public:
    MyClass(int) { }
    MyClass(int, int) { }
};

        这个类有两个构造函数,从c++11开始,都是转化构造函数。下面的例子展示了编译器自动转化像1,{1}与{1,2}这样的参数为使用转化构造函数的MyClass的实例:

void process(const MyClass& c) { }
int main()
{
    process(1);
    process({ 1 });
    process({ 1, 2 });
}

        为了阻止这样的隐式转化,两个都可以被标记为explicit:

class MyClass
{
public:
    explicit MyClass(int) { }
    explicit MyClass(int, int) { }
};

        这样修改之后,就要显式地执行这些转化了;示例如下:

process(MyClass{ 1 });
process(MyClass{ 1, 2 });

        将一个布尔型的参数显式地转化为一个判断explicit是可能的。语法如下:

explicit(true) MyClass(int);

        当然了,explicit(true)与explicit是等价的,但是对于使用类型特征的通用模板代码的上下文中就会变得很有用。对于类型特征,可以人家一起给定类型的特定属性,比如一个特定类型是否可以转化为另一个类型。这样的类型特征的结果可以用于explicit()的参数。类型特征允许书写高级的通用代码,这个我们以后再讨论吧。

        注意:推荐标注至少任一个构造函数可以用一个单个参数的explicit调用,以避免隐式转化。如果真的有隐式转化的使用情况,可以将构造函数标记为explicit(false),这样做的目的就是告诉用户你的类就是隐式转化的,是被明明白白允许的。

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

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

相关文章

大模型框架 LangChain 介绍

文章目录 langchain介绍安装依赖大模型类别千帆大模型案例常见问题 langchain介绍 是一个开源大语言模型框架&#xff0c;本身不提供大模型算法&#xff0c;只提供对接大模型算法平台的接口&#xff08;模型包裹器&#xff09;&#xff1b;langchain官网v0.2&#xff0c;内部涉…

POI获取模板文件,替换数据横纵动态表格、折线图、饼状图、折线饼状组合图

先说几个关键的点 pom.xml依赖 <dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.11.0</version> </dependency> <dependency><groupId>com.deepoove</groupId>&…

现代桌面UI框架科普及WPF入门1

现代桌面UI框架科普及WPF入门 文章目录 现代桌面UI框架科普及WPF入门桌面应用程序框架介绍过时的UI框架MFC (Microsoft Foundation Class)缺点 经典的UI框架**WinForms****QT****WPF** 未来的UI框架**MAUI****AvaloniaUI** WPF相对于Winform&#xff0c;QT&#xff0c;MFC的独立…

【深度学习】(5)--搭建卷积神经网络

文章目录 搭建卷积神经网络一、数据预处理1. 下载数据集2. 创建DataLoader&#xff08;数据加载器&#xff09; 二、搭建神经网络三、训练数据四、优化模型 总结 搭建卷积神经网络 一、数据预处理 1. 下载数据集 在PyTorch中&#xff0c;有许多封装了很多与图像相关的模型、…

二阶滤波算法总结(对RC滤波算法整理的部分修正和完善)

文章目录 1、一阶低通滤波2、一阶高通滤波3、二阶低通滤波器3.1 二阶RC低通滤波器的连续域数学模型3.2 二阶RC低通滤波器的算法推导3.3 matlab仿真 4、二阶高通滤波器4.1 二阶RC高通滤波器的连续域数学模型4.2 二阶RC高通滤波器的算法推导4.3 matlab仿真 5、陷波滤波6、带通滤波…

要大爆发的AI Agent是什么?(软件测试人员需要掌握)

什么是AI Agent&#xff1f; AI Agent 是一种软件程序&#xff0c;可以与环境交互&#xff0c;收集数据&#xff0c;并使用数据执行自主任务以实现预定目标。即人类设定目标&#xff0c;AI Agent 独立选择实现这些目标所需的最佳行动。 简单来说&#xff0c;AI Agent是一个能够…

复选框选择示例【JavaScript】

这段代码实现的功能是一个简单的复选框示例&#xff0c;它可以进行全选、反选和取消选中操作。 实现功能&#xff1a; 1. 全选&#xff1a;当点击标签"全选"旁边的复选框时&#xff0c;该页面上所有具有"item"类的复选框都会被选中&#xff08;或者取消选…

七种修复错误:由于找不到msvcr110.dll 无法继续执行的方法

当你在运行某些程序时遇到“找不到msvcr110.dll”的错误提示&#xff0c;这通常意味着你的系统缺少了Microsoft Visual C 2012 Redistributable包中的一个重要文件。这个DLL文件是Microsoft Visual C Redistributable的一部分&#xff0c;用于支持许多使用Visual C编写的软件和…

回答网友的一个SQL问题

网友问&#xff1a; CODE NAME 1 A 1 B 如何得到下面的值&#xff0c;该如何写SQL CODE NAME 1 AB 1 AB 俺的回答&#xff1a; declare t table(code varchar(50),name varchar(50)) insert into t(code,name) select 1,A union select…

【Pleiades卫星】

Pleiades卫星 Pleiades卫星是法国研制的高分辨率光学成像卫星&#xff0c;旨在满足民用和国防领域对高分辨率地球观测数据的需求。以下是对Pleiades卫星的详细介绍&#xff1a; 一、基本概况 名称&#xff1a;Pleiades&#xff0c;中文名称为昴宿星卫星。研制国家&#xff…

数电学习基础(逻辑门电路+)

1.逻辑门电路 1.1逻辑门电路的简介 1.1.1各种逻辑门电路的简介 基本概念 &#xff08;1&#xff09;实现基本逻辑运算和常用逻辑运算的电路称为逻辑门电路&#xff0c;简称门电路。逻辑门电路是组成各种数字电路的基本单元电路。将构成门电路的元器件制作一块半导体芯片上再…

Allegro视频去除走线的小方块

走线出现小方块图如下&#xff1a; 其实这种情况并不影响PCB生产和布线的联通性&#xff0c;只是多少会影响美观和性能&#xff0c;在Allegro视频中去除的方法比较简单&#xff0c;是由模块复用以后&#xff0c;没有打散模块引起的。只要我们将模块的打散即可。具体操作如下:…

stm32 gpio I/O模式以及iic访问

1&#xff0c;硬件补充连接原理图引脚 #define FLASH_BASE ((uint32_t)0x08000000) /*!< FLASH(up to 1 MB) base address in the alias region */ #define CCMDATARAM_BASE ((uint32_t)0x10000000) /*!< CCM(core coupled mem…

球体检测系统源码分享

球体检测检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer Vision …

元素循环分析再添新成员:铜、钼、镍、钴、硒微量元素数据库注释

微量营养元素&#xff08;例如Fe、Cu、Mo、Ni等&#xff09;是光合作用、呼吸作用、生物大分子合成、氧化还原平衡、细胞生长和免疫系统功能等微生物驱动过程的重要调节因子。虽然生物体需要少量的微量营养元素&#xff0c;但缺乏微量营养元素会严重限制生物体的生长和生物过程…

快手IP归属地怎么设置别的地方

在当今数字化时代&#xff0c;社交媒体平台如快手已成为人们日常生活中不可或缺的一部分。快手通过显示用户的IP归属地&#xff0c;增加了信息的透明度和互动性。然而&#xff0c;有些用户可能出于个人需求或特定情境&#xff0c;希望将自己的IP归属地设置为别的地方。本文将深…

前端开发必须了解的css知识

文本过长省略显示 单行 .ellipsis {overflow: hidden;text-overflow: ellipsis;white-space: nowrap; }多行 方法一&#xff1a; .ellipsis {overflow: hidden;text-overflow: ellipsis;-webkit-line-clamp: 3;word-break: break-all; }方法二&#xff1a; .ellipsis {ove…

分布式锁总结1 - 为什么需要分布式锁?

目录 1. 最基本的业务逻辑是&#xff1a; 2. 高并发场景下常见的缓存问题 2.1问题一 缓存穿透 : 一直查询不存在的数据 解决方案 : 短暂缓存null结果 2.2 问题二 缓存雪崩 : 大量key同时过期大量请求直击数据库 解决方案 : 在原有的过期时间上加一个随机的值&#xff0c;…

国联安基金前置机用朝天椒USB Server实现了虚拟化

国联安基金近期上线了朝天椒USB Server产品&#xff0c;影响了虚拟化进程的物理前置机逐步退出了历史舞台&#xff0c;实现了虚拟化&#xff0c;通过USB服务器&#xff0c;虚拟机中也能网络识别各个前置机系统的认证U盾。 一、背景 国联安基金在金融业务运营过程中&#xff0c…

进度条QProgressBar

进度条控价&#xff0c;用来只是任务的完成情况 值 包括当前值、最大值、最小值 // 获取和设置当前值 int value() const; void setValue(int);// 获取和设置最大值 int maximum() const; void setMaximum(int);// 获取和设置最小值 int minimum() const; void setMinimum(i…