20240416,深拷贝浅拷贝,对象初始化和清理,对象模型和THIS指针

news2024/12/26 9:20:09

 哈哈哈乌龟越狱了

目录

2.5 深拷贝&浅拷贝

2.6 初始化列表

2.7 类对象作为类成员

2.8 静态成员

2.9 成员变量和成员函数分开存储

2.10 THIS指针的用途

2.11 空指针访问成员函数

2.12 COSNT修饰成员函数

2.5 深拷贝&浅拷贝

浅拷贝:简单的赋值拷贝炒作
深拷贝:在堆区重新申请空间进行拷贝操作

浅拷贝带来的问题就是堆区的内存重复释放;深拷贝是?拷贝的时候重新申请一块内存,记录的数据是一样的,指向的内存是不一样的?

20240411,内存分区模型,new-delete语句-CSDN博客(一些根本不复习学了就忘还找不到笔记人士,乐,还好学的不多?/不是)

如果属性在堆区开辟的,一定要自己构造深拷贝函数避免出现问题

#include<iostream>
using namespace std;
class Person
{
public:
	int m_age;
	int* m_height;//指针接收
	Person()
	{
		cout << "Persong 默认构造 函数的调用" << endl;
	}
	Person(int age,int height)
	{
		m_age = age;
		m_height=new int(height);//把身高创建在堆区,new返回的是该数据类型的指针
		cout << "Persong 有参构造 函数的调用" << endl;
	}
	//系统提供的拷贝函数是浅拷贝
	//自己写一个深拷贝构造函数,解决深拷贝带来的问题
	Person(const Person &p)
	{
		m_age = p.m_age;
		//m_height = p.m_height;编译器写的
		m_height = new int(*p.m_height);
		//在堆区申请一块区域,记录*p_height的内容,即,在堆区创建数据*p_hright
		//此时new int(height)没有释放
		cout << "Persong 拷贝构造 函数的调用" << endl;
	}
	~Person()
	{
		if (m_height != NULL)
		{
			delete m_height;//释放
			m_height = NULL;//初始化
		}
		cout << "Persong 默认析构 函数的调用" << endl;//将堆区开辟的数据做释放操作
	}
};
void test01()
{
	Person p1(28,180);//执行了一次析构函数,指针指向的内存已经被释放掉了
	cout << "p1的年龄为" << p1.m_age <<"身高为"<<*p1.m_height << endl;
	Person p2(p1);
	//拷贝了m_height记录的地址,此时m_height不为空,
	//但是地址指向的地方已经被释放了,再进行一次释放,非法操作
	cout << "p2的年龄为" << p2.m_age << "身高为" << *p2.m_height << endl;
	//函数结束一起释放
}
int main()
{
	test01();
	system("pause");
	return 0;
}
2.6 初始化列表

构造函数():属性1(值 1),属性2(值2)···{ }
构造函数(int a ,int b ,```):属性1(a),属性2(b)···{ }

#include<iostream>
using namespace std;
class Person
{
public:
	int m_a;
	int m_b;
	int m_c;
	Person () :m_a(10), m_b(20), m_c(30) {}//不能修改数值
	Person(int a, int b, int c) :m_a(a),m_b(b),m_c(c){}//可以修改
};
void test01()
{
	Person p;
	Person p1(540, 23, 45);//int a=540,m_a(a)
	cout << p.m_a << "\t" << p.m_b << "\t" << p.m_c << endl;
	cout << p1.m_a << "\t" << p1.m_b << "\t" << p1.m_c << endl;
}
int main()
{
	test01();
	system("pause");
	return 0;
}
2.7 类对象作为类成员

俺的BUG:没有特意创建一个子对象,无法输出被嵌套的子对象
构造和析构的顺序相反

#include<iostream>
#include<string>
using namespace std;
class Phone
{
public:
	string m_Pname;
	Phone(string Pname)
	{
		m_Pname = Pname;
		cout << "Phone的 构造函数  调用" << endl;
	}
	~Phone()
	{
		cout << "Phone的 析构函数  调用" << endl;
	}
};
class Person
{
public:
	string m_Name;
	Phone m_Phone;
	Person(string name, string phone) :m_Name(name), m_Phone(phone) 
	{
		cout << "Person的 构造函数  调用" << endl;
	}
	~Person()
	{
		cout << "Person的 析构函数  调用" << endl;
	}//先释放PERSON的,再释放PHONE的
};
void test01()
{
	Person p("张三", "华为p60");
	cout << p.m_Name  << endl;//先构造了一个Phone类,先调用了PHONE的构造函数,再PERSON的构造函数
	//cout << p.m_Name << "拿了" << p.m_Phone << endl;//编译错误
	//说没有 操作数 能匹配<<的运算符
}
int main()
{
	test01();
	system("pause");
	return 0;
}
2.8 静态成员

静态成员变量:所有对象共享同一份数据,编译阶段分配内存,类内声明,类外初始化
静态成员函数:所有对象共享同一个函数,静态成员函数只能访问静态成员变量

#include<iostream>
#include<string>
using namespace std;

class Person
{
public:
	//(全局?共享),编译分配,类内声明&类外初始化(否则无法访问)
	static int m_a;
	int m_c;
	static void func()
	{
		m_a = 999;
		//m_c = 888;//静态成员函数只能访问静态成员变量   因为所有对象共享,无法区分m_c属于哪一个对象?
		cout << "静态成员函数  func() 的调用" << endl;
	}
private:
	//静态成员变量,函数 也有访问权限
	static int m_b;
	static void func2()
	{
		cout << "private 静态成员函数  func() 的调用" << endl;
	}
};
//类外初始化,初始化了之后,没有修改的情况下,就是100
int Person::m_a = 100;
int Person::m_b = 300;

void test01()
{
	Person p;
	cout << p.m_a << endl;//无法解析的外部符号
	Person p2;
	cout << p2.m_a << endl;//通过对象访问
	p2.m_a = 200;
	cout << p2.m_a << endl;
	cout << p.m_a << endl;//输出200,P和P1共享这一个静态变量
}
void test02()
{
	//静态成员变量,不属于某个对象上,所有对象共享同一份数据
	//两种访问方式:通过对象,通过类名
	cout << Person::m_a << endl;
	//cout << Person::m_b << endl;//m_b是私有作用域,不能类外访问
}
void test03()
{
	//静态成员函数访问:对象,类名
	Person::func();
	Person p,p1;
	p.func();
	p1.func();
	//Person::func2();无权限
}
int main()
{
	test02();//输出100
	cout << endl;
	test01();
	cout << endl;
	test02();//输出200,
	cout << endl;
	test03();
	test02();
	system("pause");
	return 0;
}
2.9 成员变量和成员函数分开存储

只有非静态的变量才在对象上

#include<iostream>
#include<string>
using namespace std;

class Person
{

};
class Pers
{
	int m_a;
	int m_b;
	static int m_c;//不属于类的对象上
	void func(){}//也
	static void func2(){}//也
};
int Pers::m_c = 800;
void test01()
{
	Person p;
	cout << "size of Person p=" << sizeof(p) << endl;
	//空对象占用内存 1
	//C++编译器会给每个空对象也分配一个字节空间,是为了区分空对象占内存的位置
	//(区分不同的空对象)每个空对象也应该有一个独一无二的内存地址
}
void test02()
{
	Pers p;
	cout << "size of Pers p=\t" << sizeof(p) << endl;//内存对齐成员变量
}
int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}
2.10 THIS指针的用途

每一个非静态成员函数只会诞生一份函数实例,也就是多个同类型的对象会公用一块代码,this指针指向被调用的成员函数所属的对象
THIS指针是隐含每一个非静态成员函数内的一种指针,不需要定义,直接使用
用途:当形参和成员变量同名时,可以用THIS指针来区分;在类的非静态成员函数中返回对象本身,可以使用 RETURN *THIS

#include<iostream>
#include<string>
using namespace std;
//解决名称冲突
class Person
{
public:
	int age;
	Person(int age)
	{
		//age = age;//编译器认为三个age是同一个,没有和成员变量区分开
		this->age = age;//this指针指向被调用的成员函数所属的对象
	}
	void Personaddage(Person& p)
	{
		this->age += p.age;//两个变量的AGE相加 || 一个变量的AGE累加
	}
	//用引用来接收
	Person& Personaddage1(Person& p)
	{
		this->age += p.age;//两个变量的AGE相加 || 一个变量的AGE累加
		return *this;//返回对象本身
	}
	Person Personaddage2(Person& p)
	{//返回值
		this->age += p.age;
		return *this;
	}
};

void test01()
{
	Person p1(18);
	cout << "p1的年龄是  " << p1.age << endl;
}
void test02()
{
	Person p(80);
	p.Personaddage(p);
	cout << "p的年龄是  " << p.age << endl;
	Person p1(2);
	p.Personaddage(p1);
	cout << "p的年龄是  " << p.age << endl;
	//p.Personaddage(p1).Personaddage(p1).Personaddage(p1).Personaddage(p1);
	//超级连加,错误,第一次函数运算完成,返回一个VOID
	p.Personaddage1(p1).Personaddage1(p1).Personaddage1(p1).Personaddage1(p1);//链式编程思想
	cout << "p的年龄是  " << p.age << endl;
	p.Personaddage2(p1).Personaddage2(p1).Personaddage2(p1).Personaddage2(p1);//链式编程思想
	//只运算了第一次,值返回就是?复制一份?和本体值相同,但是不是本体了
	cout << "p的年龄是  " << p.age << endl;
}
int main()
{
	test01();
	test02();
	system("pause");
	return 0;
}
2.11 空指针访问成员函数

C++中空指针也是可以调用成员函数,但是也要注意有么有用到THIS指针
如果用到,需要加以判断保证代码的健壮性?

#include<iostream>
#include<string>
using namespace std;
//解决名称冲突
class Person
{
public:
	int m_age;
	void showPersonName()
	{
		cout << "this is Person Class" << endl;
	}
	void showPersonAge()
	{
		if (this == NULL)
		{
			return;//不会走到下一步
		}
		cout << "m_age=" << m_age << endl;
		//cout << "m_age=" << this->m_age << endl;但是this现在是一个空指针,
	}
};

void test01()
{
	Person* p = NULL;
	p->showPersonName();
	//p->showPersonAge();//报错
}

int main()
{
	test01();
	system("pause");
	return 0;
}
2.12 COSNT修饰成员函数

成员函数后加CONST后-》常函数;常函数不可以修改成员属性,成员属性声明时加关键字MUTABLE后,常函数中依然可修改
在成员函数后加CONST,本质上修饰的时THIS指针,让指针指向的值也不可修改
常对象:声明对象前加CONST,常对象只能调用常函数

#include<iostream>
#include<string>
using namespace std;
//解决名称冲突
class Person
{
public:
	int m_age;//不能直接设置一个初始值,反而会报错受用未初始化的内存p
	mutable int m_b;//特殊变量,常函数中也可以修改
	void showage()const//(const) Person *const this
	//在成员函数后加CONST,本质上修饰的时THIS指针,让指针指向的值也不可修改
	{
		//m_age = 100;不可修改
		//this->m_age = 100;
		//this 指针的本质,指针常量,指针的指向不可修改,Person *const this
		//this = NULL;不可修改
		cout << "m_age=" << m_age << endl;
		m_b = 232;
		cout << "m_b=" << m_b << endl;//特殊变量可以修改
	}
	void func(){}
};
void test01()
{
	Person p;
	p.showage();
}
void test02()
{
	const Person p;//常对象
	//p.m_age = 1000;//不可修改
	p.m_b = 454;//可以修改
	p.showage();//常对象只能调用常函数
	//p.func();//不可以调用普通成员函数,因为普通成员函数可以修改属性
}
int main()
{
	test01();
	system("pause");
	return 0;
}

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

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

相关文章

12、【装饰器模式】动态地为对象添加新功能

你好&#xff0c;我是程序员雪球。 今天我们来聊聊 23 种设计模式中&#xff0c;一种常见的结构型模式&#xff0c;装饰器模式。聊聊它的设计思想、实现原理&#xff0c;应用场景&#xff0c;以及如何使用。 装饰器模式&#xff08;Decorator Pattern&#xff09;是一种结构型…

智慧水务是什么样的?如何打造智慧水务大屏?

在信息化和数字化快速发展的今天&#xff0c;智慧水务作为城市供水管理的重要组成部分&#xff0c;正变得越来越重要。智慧水务大屏作为智慧水务系统的可视化核心&#xff0c;不仅提升了水务管理的效率&#xff0c;而且通过数据的实时监控和分析&#xff0c;为决策者提供了强有…

揭秘爬虫技术:助你打开网络数据的大门

在当今信息爆炸的时代&#xff0c;网络上蕴藏着各种宝贵的数据资源&#xff0c;而要想获取这些宝藏&#xff0c;爬虫技术无疑是最为有效的利器之一。今天我将向大家深入探讨爬虫技术的奥秘&#xff0c;并带领大家一起走进这个数据世界的大门。 文章目录 什么是爬虫技术&#xf…

垃圾焚烧发电:从国资到专业公司,运营模式新变革|中联环保圈

近日&#xff0c;云南富源县生活垃圾焚烧发电项目运营管理技术服务招标引发广泛关注&#xff0c;与此同时&#xff0c;众多垃圾焚烧发电项目也纷纷启动了运管工作的招标。值得注意的是这些项目的招标人均为当地国资&#xff0c;且其中多数缺乏项目的运营经验。 在垃圾焚烧发电行…

4个在ArcGIS中可加载的图源分享

数据是GIS的血液。 这里分享4个来自网友分享的图源&#xff0c;该图源可以直接在ArcGIS中打开进行查看。 4个图源分享 你可以先打开ArcMap软件&#xff0c;然后将以下文分拖放到软件中打开即可查看。 4个图源 这4个图源分别为有地名和路网的地形地图、电子地图、有地名和路…

mysql-connector 交叉编译

1.下载 官网选择对应的系统以及版本&#xff0c;这里我用的是6.1.5https://downloads.mysql.com/archives/c-c/ 2.解压 tar -zxvf mysql-connector-c-6.1.5-src.tar.gz 3.先常规编译&#xff08;因为交叉编译的过程中&#xff0c;会用到生成的二进制文件&#xff09; cd m…

Llama3-8B+ LLaMA-Factory 中文微调

Llama3-8B LLaMA-Factory 中文微调 Llama3是目前开源大模型中最优秀的模型之一&#xff0c;但是原生的Llama3模型训练的中文语料占比非常低&#xff0c;因此在中文的表现方便略微欠佳&#xff01; 本教程就以Llama3-8B-Instruct开源模型为模型基座&#xff0c;通过开源程序LL…

深度相机(3D相机)

传统的RGB彩色相机称为2D相机&#xff0c; 只能得到2D的图像信息&#xff0c; 无法得到物体与相机的距离信息&#xff0c;也就是深度信息。 顾名思义&#xff0c; 深度相机除了获取2D信息&#xff0c;还能得到深度信息&#xff0c;也叫RGBD相机&#xff0c; 或3D相机。 顺便提…

人像摄影姿势入门,人像拍照姿势详解

一、资料前言 本套人像摄影资料&#xff0c;大小537.44M&#xff0c;共有17个文件。 二、资料目录 《如何摆出好POSE》.黑面.影印版.pdf 《人像摄影姿势入门》.pdf 《人像摄影技巧》.pdf 《人像摄影摆姿指南》.比尔.赫特尔.扫描版.pdf 《人像摄影摆姿全集》龙文摄影.彩图…

三羟甲基氨基甲烷(TRIS)应用场景广泛 苏州亚科科技是主要供应商

三羟甲基氨基甲烷&#xff08;TRIS&#xff09;应用场景广泛 苏州亚科科技是主要供应商 三羟甲基氨基甲烷&#xff08;TRIS&#xff09;是一种有机化合物&#xff0c;外观为白色晶体&#xff0c;溶于水。三羟甲基氨基甲烷分子结构中含有一个氮原子和三个羟基&#xff0c;反应活…

C语言指针+-整数、指针-指针、指针关系运算、指针和数组、二级指针、指针数组

文章目录 前言一、指针 - 整数二、指针 - 指针三、指针的关系运算四、指针和数组五、二级指针六、指针数组指针数组可以将几个一维数组模拟成二维数组 总结 前言 C语言指针整数、指针-指针、指针关系运算、指针和数组、二级指针、指针数组等介绍&#xff0c;还包括指针数组将几…

UE4_常见动画节点学习_Two Bone IK双骨骼IK

学习资料&#xff0c;仅供参考&#xff01; Two Bone IK 控制器将逆运动&#xff08;IK&#xff09;解算器应用于到如角色四肢等3关节链。 变量&#xff08; HandIKWeight &#xff09;被用于在角色的 hand_l 和 hand_r 控制器上驱动 关节目标位置&#xff08;Joint Target Lo…

无锡日报:用超算系统设计国产民航飞机!“神威”,再显神威!

用国产超算系统 设计国产民用飞机 ✈ 我国推进高水平科技自立自强 又迈出坚实一步 4月19日&#xff0c;来自国内航空领域和计算机领域的专家相聚国家超级计算无锡中心&#xff0c;启动“面向新一代国产超算系统的民用飞机多学科联合设计优化技术与软件”项目&#xff0c;并…

线上剧本杀小程序开发,未来行业的发展趋势?

当下&#xff0c;剧本杀成为了大众最喜欢的娱乐方式之一&#xff0c;作为以沉浸式为主的剧本杀正成为新时代下的发展潮流。 数据显示&#xff0c;剧本杀行业已达到了百亿元。面对发展迅猛的剧本杀市场&#xff0c;越来越多的资本进入到了市场中&#xff0c;剧本杀的产业链也逐…

OpenHarmony实战开发-如何实现tabContent内容可以在tabBar上显示并且tabBar可以响应滑动事件的功能。

介绍 本示例实现了tabContent内容可以在tabBar上显示并且tabBar可以响应滑动事件的功能。 效果图预览 使用说明 1.点击播放按钮进行视频播放&#xff0c;按住进度条按钮和进度条下方区域可以拖动进度条&#xff0c;更改视频播放进度。 实现思路 原生的Tabs组件&#xff0c…

微服架构基础设施环境平台搭建 -(六)Kubesphere 部署Redis服务 设置访问Redis密码

微服架构基础设施环境平台搭建 -&#xff08;六&#xff09;Kubesphere 部署Redis服务 & 设置访问Redis密码 微服架构基础设施环境平台搭建 系列文章 微服架构基础设施环境平台搭建 -&#xff08;一&#xff09;基础环境准备 微服架构基础设施环境平台搭建 -&#xff08;二…

记账本React案例(Redux管理状态)

文章目录 整体架构流程 环境搭建 创建项目 技术细节 一、别名路径配置 1.路径解析配置&#xff08;webpack&#xff09; &#xff0c;将/解析为src/ 2.路径联想配置&#xff08;vsCode&#xff09;&#xff0c;使用vscode编辑器时&#xff0c;自动联想出来src文件夹下的…

Day13.一刷数据结构算法(C语言版) 102二叉树的层序遍历;226翻转二叉树;101对称二叉树

一.102二叉树的层序遍历 二叉树的层序遍历力扣题目 1.思路分析 这道题我没有什么好的思路&#xff0c;而且力扣给的函数形式看得有点懵&#xff0c;所以我找到一个相对好理解的题解&#xff0c;具体可以参考下方链接。 力扣题解 说明&#xff1a; 返回值&#xff1a;可…

《从零开始的Java世界》10File类与IO流

《从零开始的Java世界》系列主要讲解Javase部分&#xff0c;从最简单的程序设计到面向对象编程&#xff0c;再到异常处理、常用API的使用&#xff0c;最后到注解、反射&#xff0c;涵盖Java基础所需的所有知识点。学习者应该从学会如何使用&#xff0c;到知道其实现原理全方位式…

【养生】个人参考:五脏运动

如有侵权可以下架&#xff0c;仅应用于个人查阅