20240416,对象初始化和清理,对象模型和THIS指针

news2024/11/25 4:20:58

 哈哈哈乌龟越狱了

目录

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/1600519.html

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

相关文章

如何调整Hostease服务器cPanel中的域名数量限制

近段时间我们的网站总是受到攻击&#xff0c;为了保障网站的安全&#xff0c;我们准备将所有网站迁移至Hostease提供的高防服务器中。我们的服务器配置是Intel I3 - 2120&#xff0c;8GB 内存 1TB 机械硬盘&#xff0c;100M 带宽出口&#xff0c;外加10G 防御的防御&#xff0…

Day06 - React 第六天

学习react的第六天&#xff0c;持续更新中 关注不迷路&#xff01;&#xff01;&#xff01; 使用脚手架创建一个react项目 全局下载react脚手架 npm install -g create-react-app 在需要的项目文件中创建一个react项目 create-react-app #项目名 创建好项目以后 npm或yar…

Activity——spring方式创建activiti所需数据表结构

文章目录 前言依赖引入编写数据库连接等配置配置日志文件编写java代码生成数据库表结构问题反馈与解决思路问题一&#xff1a;Cause: java.sql.SQLSyntaxErrorException: Table activiti_02.act_ge_property doesnt exist 为什么文件名必须写死&#xff1f; 前言 在之前创建ac…

java绘图在ubuntu报错

把JRT网站部署到ubuntu桌面系统上&#xff0c;开始没测试绘图部分功能&#xff0c;只试了连PostGreSql部分正常。后面试了生成位图部分发现报错。 报下面错误&#xff1a; (ColorModel.java:220)\n\tat java.desktop/java.awt.image.BufferedImage.(BufferedImage.java:286)\n…

设计模式之状态模式(上)

状态模式 1&#xff09;概述 1.定义 允许一个对象在其内部状态改变时改变它的行为&#xff0c;对象看起来似乎修改了它的类。 2.作用 状态模式用于解决系统中复杂对象的状态转换以及不同状态下行为的封装问题。 3.方案 状态模式将一个对象的状态从该对象中分离出来&…

RabbitMQ 各种通信模式的Python实现

一、RabbitMQ 原理 1、基本原理 RabbitMQ是流行的开源消息队列系统&#xff0c;用erlang语言开发。RabbitMQ是AMQP&#xff08;高级消息队列协议&#xff09;的标准实现。支持多种客户端&#xff0c;如&#xff1a;Python、Java、Javascript、C#、C/C,Go等&#xff0c;支持AJ…

【ENSP】华为三层交换机配置AAA认证,开启telnet服务

配置步骤 1.给交换机配置ip地址&#xff0c;以便登陆 2.配置AAA&#xff0c;用户名&#xff0c;密码&#xff0c;服务类型&#xff0c;用户权限 3.配置接入设备的数量 4.开启telnet服务 LSW2交换机配置 u t m #关闭提示 sys …

微信小程序scroll-view组件

一、介绍 当一个容器内容很多时&#xff0c;若容器无法显示完整内容&#xff0c;则可通过滚动操作查看所有内容 在微信小程序中scroll-view组件可以实现滚动效果 二、scroll-view组件的属性值 &#xff08;1&#xff09;scroll-x 【boolean型】 允许横向滚动条&#xff0c;默…

Python也可以合并和拆分PDF,批量高效!

PDF是最方便的文档格式&#xff0c;可以在任何设备原样且无损的打开&#xff0c;但因为PDF不可编辑&#xff0c;所以很难去拆分合并。 知乎上也有人问&#xff0c;如何对PDF进行合并和拆分&#xff1f; 看很多回答推荐了各种PDF编辑器或者网站&#xff0c;确实方法比较多。 …

HBase的数据模型与架构

官方文档&#xff1a;Apache HBase – Apache HBase™ Homehttps://hbase.apache.org/ 一、HBase概述 1.概述 HBase的技术源自Google的BigTable论文&#xff0c;HBase建立在Hadoop之上&#xff0c;是一个高可靠性、高性能、面向列、可伸缩的分布式存储系统&#xff0c;用于…

ThreadLocal和ThreadLocalHashMap

请直接百度详细介绍 -------------------------------------------------------------------------------------------------------------------------------- 1.ThreadLocalMap是Thread类里的一个局部变量 2.ThreadLocalMap是ThreadLocal类里的一个静态内部类, 3.ThreadL…

Backend - DRF 序列化(django-rest-framework)

目录 一、restful 、django-rest-framework 、swagger 三者的关系 &#xff08;一&#xff09;restful API&#xff08;REST API&#xff09; 1. rest 2. restful 3. api 4. restfulAPI &#xff08;二&#xff09;django-rest-framework&#xff08;简称DRF&#xff09…

分类算法——模型选择与调优(三)

交叉验证 交叉验证&#xff1a;将拿到的训练数据&#xff0c;分为训练和验证集。以下图为例&#xff1a;将数据分成4份&#xff0c;其中 一份作为验证集。然后经过4次&#xff08;组&#xff09;的测试&#xff0c;每次都更换不同的验证集。即得到4组模型的 结果&#xff0c;取…

进程间通信--共享内存

1.共享内存介绍 共享内存为多个进程之间共享和传递数据提供了一种有效的方式。共享内存是先在物 理内存上申请一块空间,多个进程可以将其映射到自己的虚拟地址空间中。 所有进 程都可以访问共享内存中的地址,就好像它们是由 malloc 分配的一样。如果某个进 程向共享内存写入了…

随着深度学习的兴起,浅层机器学习没有用武之地了吗?

深度学习的兴起确实在许多领域取得了显著的成功&#xff0c;尤其是那些涉及大量数据和复杂模式的识别任务&#xff0c;如图像识别、语音识别和自然语言处理等。然而&#xff0c;这并不意味着浅层机器学习&#xff08;如支持向量机、决策树、朴素贝叶斯等&#xff09;已经失去了…

Achronix FPGA增加对Bluespec提供的基于Linux的RISC-V软处理器的支持,以实现可扩展数据处理

Bluespec支持加速器功能的RISC-V处理器将Achronix的FPGA转化为可编程SoC 2024年4月——高性能FPGA芯片和嵌入式FPGA&#xff08;eFPGA&#xff09;硅知识产权&#xff08;IP&#xff09;领域的领先企业Achronix半导体公司&#xff0c;以及RISC-V工具和IP领域的行业领导者Blues…

Matlab分段微分方程组拟合【案例源码+视频教程】

专栏导读 作者简介&#xff1a;工学博士&#xff0c;高级工程师&#xff0c;专注于工业软件算法研究本文已收录于专栏&#xff1a;《复杂函数拟合案例分享》本专栏旨在提供 1.以案例的形式讲解各类复杂函数拟合的程序实现方法&#xff0c;并提供所有案例完整源码&#xff1b;2.…

OpenHarmony开发实例:【新闻客户端】

介绍 本篇Codelab我们将教会大家如何构建一个简易的OpenHarmony新闻客户端&#xff08;JS版本&#xff09;。应用包含两级页面&#xff0c;分别是主页面和详情页面&#xff0c;两个页面都展示了丰富的UI组件&#xff0c;其中详情页的实现逻辑中还展示了如何通过调用相应接口&a…

【Java NIO】那NIO为什么速度快?

Java IO在工作中其实不常用到&#xff0c;更别提NIO了。但NIO却是高效操作I/O流的必备技能&#xff0c;如顶级开源项目Kafka、Netty、RocketMQ等都采用了NIO技术&#xff0c;NIO也是大多数面试官必考的体系知识。虽然骨头有点难啃&#xff0c;但还是要慢慢消耗知识、学以致用哈…

百度智能云万源全新一代智能计算操作系统发布:引领AI新纪元,开启智能未来

随着科技的迅猛发展&#xff0c;人工智能&#xff08;AI&#xff09;逐渐渗透到我们生活的每个角落&#xff0c;为人类社会带来前所未有的变革。在这场科技革命的浪潮中&#xff0c;百度作为中国AI领域的领军企业&#xff0c;始终站在技术创新的前沿&#xff0c;不断引领行业发…