C++学习笔记----8、掌握类与对象(一)---- 对象中的动态内存分配(5)

news2024/9/28 11:22:59

2.4.2、c++23 decay copy

        如果有一个对象x,“auto y{x}”生成一个x的拷贝并且给它一个名字y;这样,它是一个左值。

c++23引入了auto(x)或者auto{x}的语法来生成一个对象x的拷贝作为右值,而不是左值。

        作为一个例子,假定前面介绍的handleMessage(string&&)函数只有右值引用,而没有左值引用重载。你应该清楚在这种情况下下面的代码是不灵的:

string value { "Hello " };
handleMessage(value); // Error

        可以使用std::move(),如下:

handleMessage(std::move(value));

        但是,这个操作之后,就不能再使用value对象了,因为它可能已经被移走了。

        使用C++23 decay-copy语法,可以写成:

handleMessage(auto { value });

        这使得value对象的临时拷贝作为一个右值并且将这个右值传递给handleMessage()。如果handleMessage()从该拷贝移走,原来的对象value保持原状不受影响。

2.4.3、实现move语法

        move语法使用右值引用来实现。给一个类增加Move语法,需要实现move构造函数和move赋值操作符。move构造函数与Move赋值操作符应该标记为noexcept告诉编译器它们不会抛出例外。这对于标准库的兼容性特别重要,作为完全兼容的实现,例如,标准库容器如果只移动保存的对象,实现move语法的话,它们也保证不会抛出例外。这么做是为了能够提供强大的例外安全。

        下面是带有move构造函数与Movem赋值操作符的Spreadsheet类的定义。两个辅助成员函数也进行了介绍:cleanup(),在析构函数与Movem赋值操作符中使用,以及moveFrom(),它从源移动数据成员到目标,然后重置源对象。

export class Spreadsheet
{
public:
	Spreadsheet(Spreadsheet&& src) noexcept; // Move constructor
	Spreadsheet& operator=(Spreadsheet&& rhs) noexcept;  // Move assignment
    // Remaining code omitted for brevity
private:
	void cleanup() noexcept;
	void moveFrom(Spreadsheet& src) noexcept;
    // Remaining code omitted for brevity
};

        实现如下:

void Spreadsheet::cleanup() noexcept
{
	for (size_t i{ 0 }; i < m_width; ++i) {
		delete[] m_cells[i];
	}
	delete[] m_cells;
	m_cells = nullptr;
	m_width = m_height = 0;
}

void Spreadsheet::moveFrom(Spreadsheet& src) noexcept
{
	// Shallow copy of data
	m_width = src.m_width;
	m_height = src.m_height;
	m_cells = src.m_cells;

	// Reset the source object, because ownership has been moved!
	src.m_width = 0;
	src.m_height = 0;
	src.m_cells = nullptr;
}

// Move constructor
Spreadsheet::Spreadsheet(Spreadsheet&& src) noexcept
{
	println("Move constructor");

	moveFrom(src);
}

// Move assignment operator
Spreadsheet& Spreadsheet::operator=(Spreadsheet&& rhs) noexcept
{
	println("Move assignment operator");

	// check for self-assignment
	if (this == &rhs) {
		return *this;
	}

	// Free the old memory and move ownership
	cleanup();

	moveFrom(rhs);

	return *this;
}

        move构造函数与move赋值操作符移动m_cells的内存属主从源对象到一个新的对象。重置源对象的m_cells指针为null指针并且 设置源对象的m_width和m_height为0以你看期间源对象的析构函数释放内存,因为新的对象现在已成为其属主。

        很明显,Move语法只有在你知道源对象不再需要时才有用。

        注意这个实现里包含了一个在Move赋值操作符中的自我赋值的检测。依赖于你的类并且依赖于你怎么将类的一个实例移动到另一个实例,该自我检测可能并不问题需要。然而,你还是应该包含它,就像我们的c++核心指导推荐中所说的那样,要保证如下代码不会在运行时产生崩溃:

sheet1 = std::move(sheet1);

        move构造函数与move赋值操作符可以显式删除或缺省,与拷贝构造函数和拷贝赋值操作符一样。

        编译器在并且只有在类没有用户声明的拷贝构造函数,拷贝赋值操作符,move赋值操作符,或者析构函数的情况下才会自动为类生成一个缺省的move构造函数。在且只有在类没有用户声明的拷贝构造函数,move构造函数,拷贝赋值操作符,或者析构函数的情况下才会为类生成一个缺省的move赋值操作符。

        警告:当你声明一个或多个特殊成员函数(析构函数,拷贝构造函数,move构造函数,拷贝赋值操作符,以及move赋值操作符)时,推荐全部声明这些函数,这被叫做五规则。或者提供显式地实现,或者显式地缺省(=default)或删除(=delete)。

2.4.4、使用std::exchange

可以使用<utility>中定义的std::exchange,来用一个新值替换并且返回旧值,示例如下:

import std;

using namespace std;

int main()
{
	int a{ 11 };
	int b{ 22 };

	println("Before exchange(): a = {}, b = {}", a, b);

	int returnedValue{ exchange(a, b) };

	println("After exchange():  a = {}, b = {}", a, b);
	println("exchange() returned: {}", returnedValue);
}

        输出如下:

Before exchange(): a = 11, b = 22
After exchange(): a = 22, b = 22
exchange() returned: 11

        exchange()函数在实现move赋值操作符时很有用。move赋值操作符需要将数据从源对象移到目标对象,这之后在源对象中的数据通常会被置成Null。前面是通过下面的代码来实现的:

void Spreadsheet::moveFrom(Spreadsheet& src) noexcept
{
    // Shallow copy of data
    m_width = src.m_width;
    m_height = src.m_height;
    m_cells = src.m_cells;

    // Reset the source object, because ownership has been moved!
    src.m_width = 0;
    src.m_height = 0;
    src.m_cells = nullptr;
}

        该成员函数从源对象拷贝m_width,m_height,和m_cells数据成员,然后将其设置成0或者nullptr,因为属主发生了转移。使用exchange()可以将代码写得更紧凑,如下:

void Spreadsheet::moveFrom(Spreadsheet& src) noexcept
{
    m_width = exchange(src.m_width, 0);
    m_height = exchange(src.m_height, 0);
    m_cells = exchange(src.m_cells, nullptr);
}

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

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

相关文章

yolo自动化项目实例解析(七)自建UI--工具栏选项

在上一章我们基本实现了关于预览窗口的显示&#xff0c;现在我们主要完善一下工具栏菜单按键 一、添加工具栏ui 1、配置文件读取 我们后面要改的东西越来越多了&#xff0c;先加个变量文件方便我们后面调用 下面我们使用的config.get意思是从./datas/setting.ini文件中读取关键…

RedisBoost Web缓存加速平台

1.产品介绍 产品名称:RedisBoost Web缓存加速平台 主要功能: 智能缓存策略配置 功能描述:RedisBoost提供了一套直观易用的缓存策略配置界面,允许用户根据业务场景自定义缓存策略,包括缓存时间(TTL)、缓存淘汰算法(如LRU、LFU)、数据分区与分片策略等。支持动态调整策…

SSM私人诊所管理系统—计算机毕业设计源码36406

摘 要 21世纪的今天&#xff0c;随着社会的不断发展与进步&#xff0c;人们对于信息科学化的认识&#xff0c;已由低层次向高层次发展&#xff0c;由原来的感性认识向理性认识提高&#xff0c;管理工作的重要性已逐渐被人们所认识&#xff0c;科学化的管理&#xff0c;使信息存…

Redis高级特性及应用

一、Redis慢查询 1.1 Redis命令流程 1.2 慢查询配置&#xff1a; 可以通过以下命令配置慢查询时间阈值&#xff08;慢查询值得是上图中执行命令的时间&#xff0c;不包含其他时间&#xff09; config set slowlog-log-slower-than 10000 //单位微秒 config rewrite //写入…

【设计模式-访问者模式】

定义 访问者模式&#xff08;Visitor Pattern&#xff09;是一种行为型设计模式&#xff0c;允许你在不修改已有类的情况下向这些类添加新的功能或行为。它通过将操作的执行逻辑从对象的类中分离出来&#xff0c;使得你可以在保持类的封闭性&#xff08;符合开闭原则&#xff…

Leetcode 740. 删除并获得点数

原题链接&#xff1a;. - 力扣&#xff08;LeetCode&#xff09; 给你一个整数数组 nums &#xff0c;你可以对它进行一些操作。 每次操作中&#xff0c;选择任意一个 nums[i] &#xff0c;删除它并获得 nums[i] 的点数。之后&#xff0c;你必须删除 所有 等于 nums[i] - 1 和…

LeetCode题练习与总结:搜索二维矩阵 Ⅱ--240

一、题目描述 编写一个高效的算法来搜索 m x n 矩阵 matrix 中的一个目标值 target 。该矩阵具有以下特性&#xff1a; 每行的元素从左到右升序排列。每列的元素从上到下升序排列。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,4,7,11,15],[2,5,8,12,19],[3,6,9,16,22],…

详细解析msyql和消息队列数据一致性问题

目录 前言 保持系统数据同步&#xff08;双写问题&#xff09; 消息队列消息丢失的问题 总结 前言 在当今互联网飞速发展的时代&#xff0c;随着业务复杂性的不断增加&#xff0c;消息队列作为一种重要的技术手段&#xff0c;越来越多地被应用于各种场景。它们不仅能有效解…

ChatGPT-o1用来进行数据分析,对比效果很惊人!

我是娜姐 迪娜学姐 &#xff0c;一个SCI医学期刊编辑&#xff0c;探索用AI工具提效论文写作和发表。 在进行数据分析的时候&#xff0c;通常有一个场景&#xff1a;我有一批数据&#xff0c;但是不知道该怎么分析&#xff0c;才能找到写论文的突破口和角度。ChatGPT能不能给我一…

Java项目实战II基于Java+Spring Boot+MySQL的厨艺交流平台设计与实现(源码+数据库+文档)

目录 一、前言 二、技术介绍 三、系统实现 四、文档参考 五、核心代码 六、源码获取 全栈码农以及毕业设计实战开发&#xff0c;CSDN平台Java领域新星创作者&#xff0c;专注于大学生项目实战开发、讲解和毕业答疑辅导。获取源码联系方式请查看文末 一、前言 在美食文化…

江协科技STM32学习- P20 实验-TIM编码器接口测速

&#x1f680;write in front&#x1f680; &#x1f50e;大家好&#xff0c;我是黄桃罐头&#xff0c;希望你看完之后&#xff0c;能对你有所帮助&#xff0c;不足请指正&#xff01;共同学习交流 &#x1f381;欢迎各位→点赞&#x1f44d; 收藏⭐️ 留言&#x1f4dd;​…

游戏厅计时器ps5计算时间的软件 佳易王电玩计时计费管理系统操作教程

一、前言 游戏厅计时器ps5计算时间的软件 佳易王电玩计时计费管理系统操作教程 软件为绿色免安装版&#xff0c;解压即可使用。 二、软件程序教程 计时的时候&#xff0c;点击 开始计时按钮 开台后可设置定时语音提醒的时间 时间设置好后&#xff0c;点击 开启提醒 即可 三、…

无人机飞手入伍当兵技术优势分析

随着现代战争形态的不断演变&#xff0c;无人机技术在军事领域的应用日益广泛&#xff0c;成为提升军队作战能力的重要手段。对于无人机飞手而言&#xff0c;其专业技能和实战经验在入伍当兵后能够转化为显著的技术优势&#xff0c;为国防事业贡献重要力量。以下是从专业技能优…

“不关心⚠️Warning”的代价:http自动升级https导致免费的存储服务扣费

背景 7 月 12 日的时候我手机突然收到一条短信&#xff1a;显示我在 LeanCloud 平台的账户欠费了。虽然只是欠费 0.01 元&#xff0c;但还是有些疑惑&#xff0c;怎么免费的存储服务突然扣费了&#xff1f; 然而这只是个开始。起初我并没有很在意这扣费的 0.01 元&#xff08;…

阿里发布Qwen2.5:编程与数学的AI新革命!

阿里发布Qwen2.5&#xff1a;编程与数学的AI新革命&#xff01; 阿里发布了Qwen2.5系列模型&#x1f680;&#xff0c;带来编程和数学领域的超强升级&#x1f9b8;‍♂️。多种规格可选&#xff0c;开源模型推动创新&#x1f513;&#xff0c;让AI助手更智能&#xff01;快来体…

一阶低通滤波器Simulink仿真测试

1、低通滤波器(SMART PLC双线性变化和后向差分对比测试 低通滤波器(SMART PLC双线性变换和后向差分对比测试)_后向差分 和 双线性-CSDN博客文章浏览阅读367次。该博客详细探讨了低通滤波器的设计,对比了SMART PLC中的双线性变换和后向差分法。内容包括Tustin变换公式、后向差…

第一批学习大模型的程序员,已经碾压同事了,薪资差距都甩出一条街了...

前言 随着人工智能技术的突飞猛进&#xff0c;AI大模型已成为引领未来的核心技术。从ChatGPT的横空出世到GPT-4o的震撼发布&#xff0c;AI技术正以前所未有的速度改变着我们的生活和工作方式。 在这场AI革命中&#xff0c;企业对AIGC人才的需求正以指数级增长。据《AIGC就业趋…

基于Hive和Hadoop的病例分析系统

本项目是一个基于大数据技术的医疗病历分析系统&#xff0c;旨在为用户提供全面的病历信息和深入的医疗数据分析。系统采用 Hadoop 平台进行大规模数据存储和处理&#xff0c;利用 MapReduce 进行数据分析和处理&#xff0c;通过 Sqoop 实现数据的导入导出&#xff0c;以 Spark…

OpenAi_Moderation审核更新

更新原文档 最新openai-python版本已不可直接用 openai.Moderation.create()

芝法酱学习笔记(0.5)——使用jenkins做自动打包

前言 上节讲了SpringBoot上的打包。但这些过程都是手动的&#xff0c;在实际的开发测试时&#xff0c;自动化的打包部署&#xff0c;可以大大提升团队开发的效率 一、去官网下载 1.1 官网安装命令 对于如何安装的问题&#xff0c;我向来推荐官网 wget -O /usr/share/keyri…