【C++】string类的深浅拷贝问题

这篇具有很好参考价值的文章主要介绍了【C++】string类的深浅拷贝问题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

浅拷贝问题

我们知道,定义一个类的时候,如果我们没有写构造,拷贝构造,赋值运算符重载,析构方法的话,编译器会自动生成。当该类成员中涉及到资源的管理时,实现的就是浅拷贝。所以,以上这几种方式是必须要程序猿手动实现的。

举例来看:
【C++】string类的深浅拷贝问题
图中所示:实现了构造和析构,没有显式定义拷贝构造,这时先创建了一个s1,当使用拷贝构造创建s2时,由于没有显式定义,编译器自动生成的实际上是直接将s1中str的值直接复制给了s2中的str,那这样就导致两个指针指向了同一块内存空间。当test函数退出时,先释放s2,调用析构函数,可以成功将s2中str指向的内存空间释放掉,接着释放s1,这时调用析构函数进行释放时,s1中的str已经是野指针了,释放野指针就会报错

因此当前代码奔溃的根本原因就是浅拷贝

浅拷贝:也称位拷贝,编译器只是将对象中的值拷贝过来。如果对象中管理资源,最后就会导致多个对象共享同一份资源,当一个对象销毁时就会将该资源释放掉,而此时另一些对象不知道该资源已经被释放,以为还有效,所以当继续对资源进项操作时,就会发生发生了访问违规。

要想实现深拷贝,我们要从逻辑上知道如何做
【C++】string类的深浅拷贝问题

每通过拷贝构造创建一个新的string对象的时候,都需要给新创建的对象开辟空间,将原对象中指向空间的内容拷贝到新空间,让原对象和新对象都拥有各自的空间,这样就可以实现深拷贝。

构造/析构函数

注意:在构造时需要进行资源管理,析构时需要进行资源释放

class String
{
public:
	String(const char* str = "")
	{
		if (str == nullptr)
			str = "";
		_str = new char[strlen(str) + 1];
		strcpy(_str, str);
	}
	~String()
	{
		if (_str)
		{
			delete[] _str;
			_str = nullptr;
		}
	}
private:
	char* _str;
};

拷贝构造/赋值运算符重载的多种写法

注意:进行拷贝构造/赋值运算符重载时,有多种写法,主要分为传统版和现代版,为了实现深拷贝,实际上要让新创建的string对象拥有各自的空间。

//传统版:代码易懂,但是代码重复率高
	String(const String& s)
		:_str(new char[strlen(s._str)+1])// 给当前对象的指针变量new一段空间,+1是为了存放'\0'
	{
	    // 将s中指向空间的内容拷贝到当前对象,当前对象就拥有了和s相同内容的空间,但是两份空间是独立的
		strcpy(_str, s._str);
	}
	String& operator=(const String& s)
	{
		//需要判断是否为自己给自己赋值
		if (this != &s)
		{
			//先创建一个临时指针,空间大小和s中指针指向的空间一致
			char* tmp = new char[strlen(s._str) + 1];
			//将其内容拷贝至tmp中
			strcpy(tmp, s._str);
			//释放旧空间
			delete[] _str;
			//将指针指向修改为新指向
			_str = tmp;
		}
		return *this;
	}

现代版的写法,省去了重复的new和strcpy,而是直接使用swap,交换两个指针的指向即可,临时对象在函数结束时调用析构函数释放资源,将临时对象原来指向的空间返回给需要空间的对象。文章来源地址https://www.toymoban.com/news/detail-426066.html

//现代版:代码简洁,但是不易理解
	String(const String& s)
		:_str(nullptr)//后续需要将tmp中指针指向改为nullptr,调用析构函数释放时就不做任何操作了
	{
		//用构造函数构造一个临时对象
		String tmp(s._str);
		//将当前对象中的指针指向和临时对象中指针指向交换,当前对象就拥有和s中指针指向相同内容的空间,
		//同时,tmp中指针的指向是nullptr,调用析构函数释放时也不需要做任何操作
		swap(_str, tmp._str);
	}
	// 传址方式的赋值运算符重载
	String& operator=(const String& s)
	{
		if (this != &s)
		{
			String tmp(s._str);
			//调用析构函数时,_str释放的是原来tmp的空间,tmp释放的是原来_str的旧空间
			swap(_str, tmp._str);
		}
		return *this;
	}
	// 传值方式的赋值运算符重载
	String& operator=(String s)
	{
		//以传值方式传递时,s是原来s的临时拷贝,可以直接通过交换的方式,
		//让_str获得临时s指针指向的内容,临时s释放的是原来_str的旧空间
		swap(_str, s._str);
		return *this;
	}

到了这里,关于【C++】string类的深浅拷贝问题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • C++中类的6个默认成员函数 【拷贝构造函数】

    在前几章学习对象的时候,我们有的时候需要一个与已存在对象一某一样的新对象 那在创建对象时,可否创建一个与已存在对象一某一样的新对象呢? 拷贝构造函数:只有单个形参,该形参是对本类类型对象的引用(一般常用const修饰),在用已存在的类类型对象创建新对象时

    2024年02月20日
    浏览(41)
  • 【c++】string类的使用

    目录 一、标准库中的string类 1、简单介绍string类 2、string类的常用接口注意事项 2.1、string类对象的常用构造 2.2、string类对象的容量操作 2.3、string类对象的访问及遍历操作 2.4、string类对象的修改操作 二、string类的模拟实现         (1)string是表示字符串的字符串类;    

    2024年02月01日
    浏览(62)
  • 深浅拷贝、函数

    普通函数 1、函数的定义与特性 2、函数的创建 3、函数的参数 4、函数的返回值 5、可变与不可变数据类型 6、作用域 递归函数 匿名函数 高级函数 装饰器 1、闭包 2、装饰器 3、装饰器之登录练习 列表生成式 1、列表推导式的概念 2、基本的使用方式 3、在循环的过程中使用i

    2024年02月03日
    浏览(24)
  • python的深浅拷贝

    copy函数是浅拷贝,只对可变类型的第一层对象进行拷贝,对拷贝的对象开辟新的内存空间进行存储,不会拷贝对象内部的子对象。对于不可变对象而言,浅拷贝只是引用赋值。 deepcopy函数是深拷贝,对于可变类型,深拷贝是逐层进行拷贝。对于不可变类型而言,也是引用赋值

    2024年02月12日
    浏览(23)
  • 深浅拷贝,温故知新

    1.1、概念 对象的深拷贝是指其属性与其拷贝的源对象的属性不共享相同的引用(指向相同的底层值)的副本。 因此,当你更改源或副本时,可以确保不会导致其他对象也发生更改;也就是说,你不会无意中对源或副本造成意料之外的更改。 在深拷贝中,源和副本是完全独立

    2024年02月03日
    浏览(32)
  • JavaScript深浅拷贝

    1. js浅拷贝只是创建了一个新的对象,复制了原有对象的基本类型的值。 手写实现  2. 深拷贝的原理和实现 将一个对象从内存中完整地拷贝出来一份给目标对象,并从堆内存中开辟一个全新的空间存放新的对象,且新对象的修改并不会改变原对象,二者实现真正的分离

    2024年01月18日
    浏览(32)
  • 浅析深浅拷贝

           我们在对对象进行复制时就用到深浅拷贝。 一、普通复制 控制台打印结果:               之所以我们要用到拷贝,是因为直接赋值的复制可能不能满足我们的需求。向上面代码所展示的,我们复制代码时,复制到的是 地址 ,所以对 复制体修改实际修改的是原对

    2024年02月12日
    浏览(22)
  • 认识Object类和深浅拷贝

    本文介绍了Object类以及Object类部分方法,toString方法,equals和hashCode方法(重写前和重写后的对比),getClass方法,clone方法,以及拷贝新对象时会出现的深浅拷贝, 内容较长,耗时一天,建议收藏后观看~ Object类是Java默认提供的一个类。而这个类是Java里所有类的顶级父类,即在继承体系下

    2023年04月20日
    浏览(22)
  • C++ String类的基本使用

            放弃时间的人,时间也会放弃他。——莎士比亚 ; 本篇章是关于string类内一些函数的介绍以及使用方法,都是我们编程必须掌握的基础! ​ 全文共7000字左右. 话不多说安全带系好,发车啦 (建议电脑观看) 。 附:红色,部分为重点部分;蓝颜色为需要记忆的

    2024年02月09日
    浏览(30)
  • 【C++】String类的模拟实现。

    🎉博客主页:小智_x0___0x_ 🎉欢迎关注:👍点赞🙌收藏✍️留言 🎉系列专栏:C++初阶 🎉代码仓库:小智的代码仓库 string类中需要三个成员变量分别记录元素个数、容量和内容。还需要一个 size_t 类型npos-1表示整型的最大值。 这段代码是 string 类的构造函数。构造函数是在

    2024年02月13日
    浏览(28)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包