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)
上一篇 2022年10月1日 下午9:46
下一篇 2022年10月1日 下午10:00


相关推荐

  • Linux下的动态库和静态库详解

    Linux下的动态库和静态库详解动态库和静态库文章目录动态库和静态库静态库与动态库的概念理解动静态库如何打包动静态库与如何使用动静态库如何制作打包动态库为什么我们要使用别人 一般是顶尖的工程师写的 的代码 为了开发效率和鲁棒性 健壮性 如何使用别人的功能 1 库 2 开源代码 3 基本的网络功能调用 各自网络接口 语音识别 库一般分为动态库和静态库 动态库一般的命名为 libc so 静态库一般的命名为 libc a 去掉前缀 lib 去掉 之后的内容 剩下的就是库的名字 这里就是 c 库 生成可执行程序的方式有两种 动态链接和

    2026年3月16日
    2
  • Android开发环境配置

    Android开发环境配置本文是Android开发环境的搭建教程,最近用到了Android开发,对环境搭建做个总结。1、安装JDK首先去官网下载JDK。JavaSeSdk下载地址:https://www.oracle.com/java/technologies/javase-downloads.html选择Windows版本。下载完成后,直接双击安装,使用默认路径C:\ProgramFiles\Java\jdk-17.0.2即可。然后配置环境变量。然后,运行CMD,输入java-version。如上图,看到

    2022年7月23日
    12
  • 微信小程序+php 授权登陆,完整代码

    微信小程序+php 授权登陆,完整代码先上图实现流程:1、授权登陆按钮和正文信息放到了同一个页面,未授权的时候显示登陆按钮,已授权的时候隐藏登陆按钮,显示正文信息,当然也可以授权和正文分开成两个页面,在授权页面的onload里判断是否

    2022年7月3日
    28
  • Python二维数组与三维数组切片详解

    Python二维数组与三维数组切片详解文章目录 x n x n x m n x m n 如果对象是二维数组 则切片应当是 x 的形式 里面有一个冒号 冒号之前和之后分别表示对象的第 0 个维度和第 1 个维度 如果对象是三维数组 则切片应当是 x 里面有两个冒号 分割出三个间隔 三个间隔的前 中和后分别表示对象的第 0 1 2 个维度 x n x n x m n x m n

    2026年3月19日
    3
  • 〖Python零基础入门篇(61)〗- Python 中的迭代器

    〖Python零基础入门篇(61)〗- Python 中的迭代器该章节我们来学习一下 Python 中的一个新的概念 那就是迭代器 迭代器的使用可以帮助我们提升代码的性能 接下来让我们看一下关于迭代器 我们需要学习一下哪些内容

    2026年3月17日
    1
  • 欠采样与过采样方法

    欠采样与过采样方法使用 SMOTE 过采样时应先切分训练集和验证集 再对训练集进行过采样 否则将会导致严重的过拟合 https beckernick github io oversampling modeling 使用方法 X train X val y train y val train test split train df predictors train df target

    2026年3月17日
    3

发表回复

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

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