Copy and Swap技术-安全自我赋值

这篇具有很好参考价值的文章主要介绍了Copy and Swap技术-安全自我赋值。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

        关于C++的赋值运算符的重写,effective C++上已经有足够详细的描述,但是对于拷贝交换技术只是简单的提及,作者对此的看法是不提倡。我认为事实上拷贝交换技术还是非常有学习和应用的必要的,其关键在于,把一切编译器可以完成的工作完全交给编译器去做,而不是由我们去手工实现,从而避免了很多错误。

什么时候需要copy-swap?

        构造一个类去管理另外一个类时,需要遵循一个原则( The Rule of Three ),拷贝构造函数,赋值函数,析构函数,如果显示的实现其中一个,其他的都需要显示实现。

原则是什么?

copy-swap是解决方案,可以很好地协助赋值运算符实现两件事:避免代码重复,并提供强大的异常保证。

工作原理?

        从概念上讲,它通过使用拷贝构造函数的功能来创建数据的本地副本,然后使用交换功能获取复制的数据,将旧数据与新数据交换来工作。然后,临时副本将销毁,并随身携带旧数据。我们剩下的是新数据的副本。

为了使用copy-swap,我们需要三件事:

  1. 一个有效的拷贝构造函数
  2. 一个有效的析构函数
  3. 一个自定义的交换函数,不能用std::swap,因为该函数实现中调用了拷贝构造和复制函数,且交换函数不抛异常

示例

class Test
{
public:
	Test(int a, int b):m_nA(a),m_pB(new int(b))
	{
		cout << "构造:m_a:" << m_nA << " " << *m_pB << endl;
	}
	Test(const Test& obj)
	{
		this->m_nA = obj.m_nA;
		this->m_pB = new int(*obj.m_pB);		
	}

	Test& operator=(const Test& obj)
	{
		if (this != &obj)//避免自我赋值
		{
			delete m_pB;
			this->m_nA = obj.m_nA;
			this->m_pB = new int(*obj.m_pB);//可能失败
		}

		return *this;//返回*this的引用
	}

	~Test()
	{
		
		if (m_pB)
		{
			cout << "析构:m_a:" << m_nA << " " << *m_pB << endl;
			delete m_pB;
			m_pB = nullptr;
		}
	}
private:
	int m_nA;
	int* m_pB{nullptr};
};

        可以看到我们的代码几乎是对拷贝构造函数和析构函数的完全复制,此外,上述代码虽然完成了自赋值的验证,但并未保障异常安全。一旦new失败,原this对象的m_pB已经被删除,因此会引发异常。

下面给出另一种写法:

void swapEx(Test& obj)
	{
		using std::swap;
		swap(this->m_nA, obj.m_nA);
		swap(this->m_pB, obj.m_pB);
	}
	Test& operator=(const Test& obj)
	{
		if (this != &obj)//避免自我赋值
		{
			Test tmp(obj);
			swapEx(tmp);
		}

		return *this;
	}

        上述第一个方法事实上是致命的。在不考虑继承关系的复杂情况下,如果更改类A,添加数据成员,我们在修改其它构造/析构函数的同时,也必须修改赋值运算符。copy and swap技术则可以做到完全规避这一点,此外,所有调用工作由编译器自动完成,无需再做任何额外操作。
该技术的核心就是不再使用引用作为赋值运算符参数,形参将直接是对象,这样的写法将会使编译器自动调用拷贝构造函数,由于拷贝构造函数的调用,异常安全将在进入函数体之前被避免(若拷贝失败则什么都不会发生)。经过swap后的对象在离开函数体后会自动销毁,因此也就自动调用了析构函数。

参考链接:https://blog.csdn.net/hiwubihe/article/details/116667884
参考链接:https://blog.csdn.net/feifeiiong/article/details/77866579文章来源地址https://www.toymoban.com/news/detail-410728.html

到了这里,关于Copy and Swap技术-安全自我赋值的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【Java基础】CAS (Compare And Swap) 操作

    关于作者:CSDN内容合伙人、技术专家, 从零开始做日活千万级APP。 专注于分享各领域原创系列文章 ,擅长java后端、移动开发、人工智能等,希望大家多多支持。 我们继续总结学习 Java基础知识 ,温故知新。 CAS其实就是Compare And Swap的一个缩写,顾名思义就是比较并交换,

    2024年02月13日
    浏览(50)
  • CAS是“Compare and Swap“(比较并交换)

    CAS是\\\"Compare and Swap\\\"(比较并交换)的缩写,是一种多线程同步的原子操作。它基于硬件的原子性保证,用于解决并发环境下的数据竞争和线程安全问题。 CAS操作包括三个参数:内存地址V、旧的预期值A和新的值B。它的执行步骤如下: 从内存中读取V的当前值; 比较当前值与预

    2024年02月08日
    浏览(55)
  • python赋值运算符,及查询表

    python的赋值运算符也是十分重要的,因为软件程序的基本工作就是接收数据,处理数据存储数据,然后响应请求发送数据,这整个过程通常都需要通过计算机指令将各种各样的值赋值给变量,来存储数据,以供计算机处理。 那么,在python当中,我们是如何将数据赋值给变量的

    2024年02月07日
    浏览(56)
  • Java基础入门篇——赋值运算符(九)

    赋值运算符的作用是将一个数值、变量或者表达式的值赋给某一个变量。在赋值过程中,运算顺序从右往左,将右边表达式的结果赋值给左边的变量。 【=】赋值,用法:a=10,将10赋值给变量a; 【+=】相加后赋值,用法:a+=b,等价于a=a+b,将a+b的值赋给a; 【-=】相减后赋值,

    2024年02月14日
    浏览(66)
  • c++拷贝构造与赋值运算符重载

    目录 目录:         1:拷贝构造         2:赋值运算符重载                  前言:在上一章我们已经学习过了,构造与析构这两个默认成员函数了,接下来让我们一起来学习另外两个重要的默认成员函数。         首先让我们来讲一下默认成员函数这个概念,所谓

    2024年02月08日
    浏览(54)
  • 【C++】详解运算符重载,赋值运算符重载,++运算符重载

    目录 前言 运算符重载 概念 目的 写法 调用 注意事项 详解注意事项 运算符重载成全局性的弊端 类中隐含的this指针 赋值运算符重载 赋值运算符重载格式 注意点 明晰赋值运算符重载函数的调用 连续赋值 传引用与传值返回 默认赋值运算符重载 前置++和后置++重载 先梳理一下

    2024年04月25日
    浏览(79)
  • C++奇迹之旅:深入理解赋值运算符重载

    运算符重载是C++中的一个重要特性,他允许我们为自定义的类型定义自己的运算符行为。通过运算符重载, 我们可以使用与内置数据类型相同的语法来操作自定义类型,从而提高代码的可读性和可维护性 。 还是我们熟悉的日期函数: 然后我们定义两个日期对象d1和d2: 当你想

    2024年04月26日
    浏览(39)
  • 逍遥自在学C语言 | 赋值运算符

    在C语言中,赋值运算符用于将一个值赋给变量 这个过程分为两个步骤: 计算赋值运算符右侧的表达式 将结果赋给左侧的变量。 C语言提供了多个不同的赋值运算符,包括基本的赋值运算符、复合赋值运算符以及条件赋值运算符等 第一位闪亮登场,有请今后会一直教我们C语

    2023年04月24日
    浏览(54)
  • 【C++】:拷贝构造函数和赋值运算符重载

    拷贝构造函数是特殊的构造函数。 是用一个已经存在的对象,赋值拷贝给另一个新创建的已经存在的对象 。 本质:用同类型的对象拷贝初始化 。 拷贝构造函数也是 特殊的成员函数 ,其特征如下: 2.1 拷贝构造函数是构造函数的一个重载形式。 2.2 拷贝构造函数的 函数名域

    2024年04月28日
    浏览(44)
  • C++拷贝构造函数与赋值运算符重载

    顾得泉: 个人主页 个人专栏: 《Linux操作系统》 《C++从入门到精通》  《LeedCode刷题》 键盘敲烂,年薪百万!        在现实生活中,可能存在一个与你一样的自己,我们称其为双胞胎。        那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢?  

    2024年02月22日
    浏览(46)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包