C++面试题之浅拷贝和深拷贝的区别「建议收藏」

C++面试题之浅拷贝和深拷贝的区别「建议收藏」先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。先看一个例子,有一个学生类,数据成员时学生的人数和名字:#include<iostream>usingnamespacestd;classStudent{private: intnum; c…

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

       先考虑一种情况,对一个已知对象进行拷贝,编译系统会自动调用一种构造函数——拷贝构造函数,如果用户未定义拷贝构造函数,则会调用默认拷贝构造函数。

       先看一个例子,有一个学生类,数据成员时学生的人数和名字:

#include <iostream>  
using namespace std;

class Student
{
private:
	int num;
	char *name;
public:
	Student();
	~Student();
};

Student::Student()
{
	name = new char(20);
	cout << "Student" << endl;

}
Student::~Student()
{
	cout << "~Student " << (int)name << endl;
	delete name;
	name = NULL;
}

int main()
{
	{// 花括号让s1和s2变成局部对象,方便测试
		Student s1;
		Student s2(s1);// 复制对象
	}
	system("pause");
	return 0;
}

C++面试题之浅拷贝和深拷贝的区别「建议收藏」
       执行结果:调用一次构造函数,调用两次析构函数,两个对象的指针成员所指内存相同,这会导致什么问题呢?name指针被分配一次内存,但是程序结束时该内存却被释放了两次,会导致崩溃!

C++面试题之浅拷贝和深拷贝的区别「建议收藏」

 

       这是由于编译系统在我们没有自己定义拷贝构造函数时,会在拷贝对象时调用默认拷贝构造函数,进行的是浅拷贝!即对指针name拷贝后会出现两个指针指向同一个内存空间。

 

C++面试题之浅拷贝和深拷贝的区别「建议收藏」

       所以,在对含有指针成员的对象进行拷贝时,必须要自己定义拷贝构造函数,使拷贝后的对象指针成员有自己的内存空间,即进行深拷贝,这样就避免了内存泄漏发生。

        添加了自己定义拷贝构造函数的例子:

#include <iostream>  
using namespace std;

class Student
{
private:
	int num;
	char *name;
public:
	Student();
	~Student();
	Student(const Student &s);//拷贝构造函数,const防止对象被改变
};

Student::Student()
{
	name = new char(20);
	cout << "Student" << endl;

}
Student::~Student()
{
	cout << "~Student " << (int)name << endl;
	delete name;
	name = NULL;
}
Student::Student(const Student &s)
{
	name = new char(20);
	memcpy(name, s.name, strlen(s.name));
	cout << "copy Student" << endl;
}

int main()
{
	{// 花括号让s1和s2变成局部对象,方便测试
		Student s1;
		Student s2(s1);// 复制对象
	}
	system("pause");
	return 0;
}

C++面试题之浅拷贝和深拷贝的区别「建议收藏」
        执行结果:调用一次构造函数,一次自定义拷贝构造函数,两次析构函数。两个对象的指针成员所指内存不同。
 总结:浅拷贝只是对指针的拷贝,拷贝后两个指针指向同一个内存空间,深拷贝不但对指针进行拷贝,而且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不同地址的指针。
再说几句:
当对象中存在指针成员时,除了在复制对象时需要考虑自定义拷贝构造函数,还应该考虑以下两种情形:
1.当函数的参数为对象时,实参传递给形参的实际上是实参的一个拷贝对象,系统自动通过拷贝构造函数实现;
2.当函数的返回值为一个对象时,该对象实际上是函数内对象的一个拷贝,用于返回函数调用处。

 

3.浅拷贝带来问题的本质在于析构函数释放多次堆内存,使用std::shared_ptr,可以完美解决这个问题。

 

关于std::shared_ptr的原理和实现可参考:C++笔试题之smart pointer的实现

一个完整的自定义类实现可参考:C++笔试题之String类的实现

 

参考链接:https://www.cnblogs.com/always-chang/p/6107437.html

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/186966.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • RTP协议与实战

    RTP协议与实战一.前言二.RTP协议三.使用jrtplib发送RTP数据包

    2022年6月28日
    34
  • WPF布局之WrapPanel与StackPanel

    WPF布局之WrapPanel与StackPanel转载:https://www.cnblogs.com/Im-Victor/p/10565030.html三.WrapPanelWrapPanel布局面板将各个控件从左至右按照行或列的顺序罗列,当长度或高度不够是就会自动调整进行换行,后续排序按照从上至下或从右至左的顺序进行。Orientation——根据内容自动换行。当Horizontal选项看上去类似于Windows资源管理器的缩略图视图:元素是从左向右排列的,然后自上至下自动换行。Vertical选项看上去类似于Windows资源..

    2022年7月23日
    13
  • c++ 二维vector_vector如何重置

    c++ 二维vector_vector如何重置初始化二维vector,为r*c的vector,所有值为0.1.直接用初始化方法(刚开始没想到)vector>newOne(r,vector(c,0));2.用resize()来控制大小vector>res;res.resize(r);//r行for(intk=0;k

    2022年9月18日
    0
  • javaweb-springMVC-55

    javaweb-springMVC-55

    2021年5月18日
    129
  • lofter限流怎么解决_高并发限流

    lofter限流怎么解决_高并发限流前言:学习本篇博客是有一些前提基础的1、熟悉gateway网关使用2、熟悉nginx使用3、熟悉sentinel的应用,会涉及网关规则持久化改造看不懂的童鞋们可以补一下微服务gateway网关和Sentinel相关知识秒杀链路兜底方案之限流&降级实战一、秒杀场景介绍1.1秒杀场景的特点1.2流量消峰1.3兜底方案二、限流实战2.1nginx限流(https://nginx.org/en/docs)2.2网关限流2.2.1网关接入sentinel控制台2.2.2Sentinel

    2022年10月6日
    2
  • nginx实现tomcat动静分离详解

    nginx实现tomcat动静分离详解1.为什么要实现动静分离1)nginx的处理静态资源能力超强主要是nginx处理静态页面的效率远高于tomcat的处理能力,如果tomcat的请求量为1000次,则nginx的请求量为6000次,tomcat每秒的吞吐量为0.6M,nginx的每秒吞吐量为3.6M,可以说,nginx处理静态资源的能力是tomcat处理能力的6倍,优势可见一斑。2)动态资源和静态资源分开,使服务器结构更

    2022年6月4日
    29

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号