C++复习笔记7

news2024/9/24 7:26:14

1.C++内存分区

C++内存分区:代码区:存放函数体的二进制代码,由操作系统管理

全局区:存放全局变量静态变量和常量。

栈区:编译器分配,存放函数的参数值和局部变量等。

堆区:由程序员分配和释放,若程序员不释放,程序结束时由操作系统回收。

内存分区的意义:不同区域存放的数据,赋予不同的生命周期,让变成更加灵活。

之前写的代码都存放在代码区。

程序编译后,生成exe可执行程序,未执行该程序前分为两个区域。(未运行前的两个区)

代码区:

存放CPU执行的机器指令

代码区是共享的(对于频繁被执行的程序,在内存中只保存一份即可)

代码区是只读的(防止程序意外地修改了它的指令)

全局区:

全局变量和静态变量存放在此

全局区包含常量:字符串常量和其它常量

该区域的数据在程序结束后由操作系统释放。

const修饰的局部变量作为常量貌似存在了栈区呢?

#include<iostream>
using namespace std;
//创建全局变量
int g_a = 10;
int g_b = 10;

const int c_g_a = 10;

int main()
{
	//创建普通的局部变量
	int a = 10;
	int b = 10;

	cout << "局部变量a的地址为:" << (int)&a << endl;
	cout << "局部变量b的地址为:" << (int)&b << endl;

	cout << "全局变量g_a的地址为:" << (int)&g_a << endl;
	cout << "全局变量g_b的地址为:" << (int)&g_b << endl;
   
	static int s_a = 10;
	static int s_b = 10;
	cout << "静态变量s_a的地址为:" << (int)&s_a << endl;
	cout << "静态变量s_b的地址为:" << (int)&s_b << endl;
	
	//常量分为字符串常量和const修饰的变量,const可以修饰局部变量和全局变量
	cout << "字符串常量的地址为:" << (int)&"Hello World" << endl;

	//const修饰的局部变量
	const int c_s_a = 10;
	cout << "const修饰的局部变量的地址为:" << (int)&c_s_a << endl;

	//const修饰的全局变量
	cout << "const修饰的全局变量的地址为:" << (int)&c_g_a << endl;
	
	system("pause");
	return 0;
}

 c语言利用malloc函数和free函数申请堆区空间:

1.要自己计算大小 2.要把返回的void*强转为其他类型指针 3.要判断返回值是否为NULL。

需要动态申请内存空间的两个场景:

(1).开辟的连续数组空间大小只有运行后才能确定

//栈:局部变量 函数的参数
//堆: malloc new
//静态常量: static 字符串常量
//int* ptr = malloc(); //指针在栈区,申请的空间在堆区

//malloc calloc realloc _alloca
#include<iostream>
using namespace std;

void main()
{
	int n;
	cin >> n;
	int ar[10] = { 0 };

	int* ptr = (int*)malloc(sizeof(int) * n);//动态开辟空间需求1 数组
	{
		if (NULL == ptr)
		{
			cout << "Out of Memory" << endl;
			return;
		}
		free(ptr);
		ptr = NULL;
	}

	if (ptr != NULL)
	{
		*ptr = 10;
	}

}

(2)成员变量的指针开辟空间,存放数据。

class Stu
{
public:
	Stu(const char* name, int age)
	{
		//m_name = name;//指针不能直接赋值
		this->m_name = (char*)malloc(strlen(name) + 1);//动态内存申请需求1 构造函数
		strcpy(m_name, name);
		this->m_age = age;

	}

private:
	char* m_name;
	int m_age;
};

void test02()
{
	Stu s("abc", 20);
}

int main()
{
	test01();
	system("pause");
	return 0;
}

C语言_alloca函数在栈区动态开辟空间,不能free释放,比较特殊。

//void* _alloca(size_t size);

void test01()
{
	int* ptr = (int*)_alloca(sizeof(int) * 10);
	//free(ptr);//栈区申请,不用释放
}

c++中的new和delete操作符也是在堆区申请和释放空间的。

1.new delete 开辟或者释放单个对象的空间。new [] 和delete[]申请和释放多个连续的对象空间,相当于搞了一个数组。

2.new操作符不用计算开辟空间大小,不用强转指针,不用判空。

3.malloc free new delete底层实现不一样,不能混用。

4.new 和delete 会调用构造函数,new Test[10]就调用10次,析构也一样。new[]和delete[]必须对应,不然会出现内存泄漏。注意顺序是new开辟空间->调用构造函数->调用析构函数->delete释放空间

5.new对象数组时,类必须有默认构造函数。

6.操作符new和操作符delete即operator new 和operator dalete重载是通过malloc和free实现的,它们的功能仅申请空间,与构造析构无关。

7.打断点可以发现,使用new 和 delete操作符时,会先调用operator new开辟空间,然后调用构造函数进行初始化,接下来调用析构函数销毁数据,最后调用operator delete释放空间。

8.实际在编译器底层也是对new和delete操作符进行了多种重载,执行重载的同时 调用了构造和析构函数。

#include<iostream>
using namespace std;

//c++

//重载new
void* operator new(size_t sz)//无符号类型整形
{
	void* ptr = malloc(sz);
	return ptr;
}

void operator delete(void* ptr)
{
	free(ptr);
}

void* operator new[](size_t sz)//无符号类型整形
{
	void* ptr = malloc(sz);
	return ptr;
}

void operator delete[](void* ptr)
{
	free(ptr);
}

void test00()
{
	int* ptr = (int*)malloc(sizeof(int)*10);
	if (NULL != ptr)
	{
		cout << "Out of mamery" << endl;
		return;
	}
	free(ptr);
}

void test01()
{
	int* ptr = new int;
	*ptr = 10;

	delete ptr;
}

void test02()
{
	int* ptr = new int[10];
	delete[] ptr;
}

void test03()
{
	int* ptr1 = (int*)malloc(sizeof(int));
	*ptr1 = 10;
	free(ptr1);

	int* ptr2 = new int(10);
	delete ptr2;
}

class Test
{
public:
	Test(int d=0)
	{
		this->m_data;
		cout << "Creat Test Obj" <<endl;
	}
     
	~Test()
	{
		cout << "Destory Test Obj" << endl;
	}
private:
	int m_data;
};

void test04()
{
	//Test t;
	Test* pt1 = (Test*)malloc(sizeof(Test));//空间申请和空间释放
	free(pt1);

	Test* pt2 = new Test(10);//1申请空间,2初始化对象(调用构造函数)//new操作符
	delete pt2;              //1调用析构函数 2释放空间
}

void test05()
{
	Test* ptr = new Test[10];//new对象数组时,类必须有默认构造函数
	//delete ptr;//malloc 和free不能混用,底层记录的信息和实现细节不对应
	delete[] ptr;
}

void test06()
{
	Test* ptr = new Test;
	delete ptr;
}

void test07()
{
	Test* ptr = (Test*)operator new(sizeof(Test));//操作符new,不调用构造析构仅申请释放
	operator delete(ptr);
}

int main()
{
	test07();

	system("pause");
	return 0;
}

回调函数来处理申请失败的问题。

void OutOfMemory(void)
{
	cout << "OutOfMemory" << endl;
	exit(1);
}

void test01()
{
	set_new_handler(OutOfMemory);
	int* ptr = new int[536870911];
    
	if (ptr == NULL)
	{
		cout << "aaaaaaaaaaaaa" << endl;
	}
	cout << "bbbbbbbbbbbbbb" << endl;
}

       new和delete也可以在类内重载,类内有优先调用类内的,没有就调全局的,再没有就调底层已经实现的。

class Test
{
public:
	void* operator new(size_t sz)//无符号类型整形
  	{
		void* ptr = malloc(sz);
		return ptr;
	}

	void operator delete(void* ptr)
	{
		free(ptr);
	}

	void* operator new[](size_t sz)//无符号类型整形
	{
		void* ptr = malloc(sz);
		return ptr;
	}

		void operator delete[](void* ptr)
	{
		free(ptr);
	}

	
	Test(int d = 0)
	{
		this->m_data;
		cout << "Creat Test Obj" << endl;
	}

	~Test()
	{
		cout << "Destory Test Obj" << endl;
	}
private:
	int m_data;
};

void test02()
{
	int* ptr = new int;//调全局
	Test* pt = new Test;//调类内
}

 针对内置数据类型进行申请时,malloc和new区别不大。

#include<iostream>
using namespace std;

void test01()
{
	//申请内置数据类型区别不大
	int* ptr = (int*)malloc(sizeof(int));
	int* ptr2 = new int;
}

int main()
{
	test01();
	system("pause");
	return 0;
}

定位new表达式在实际中一般是配合内存池使用。因为内存池分配出的内存没有初始化,所以如果是自定义类型的对象,需要使用new的定义表达式进行显示调构造函数进行初始化。

定位new,在原有空间的指定位置放一个对象,这个对象是在堆上new出来的。基本语法如下:

#include<iostream>
using namespace std;

class Test;

void* operator new(size_t sz, void* ptr, int pos)
{
	return &((int*)ptr)[pos];
}

class Test
{
public:

	Test(int d = 0)
	{
		this->m_data=d;
		//cout << "Creat Test Obj" << endl;
	}

	~Test()
	{
		//cout << "Destory Test Obj" << endl;
	}
private:
	int m_data;
};

void test01()
{
	//int* ptr = (int*)malloc(sizeof(int)*10);
    //定位new
	int ptr[10];
	Test t[10];

	//new(ptr,5) int(100);
	 new (t, 5) Test(200);

}

int main()
{
	test01();
	system("pause");
	return 0;
}

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

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

相关文章

IntelliJ IDEA 创建JavaFX项目运行

IntelliJ IDEA 创建JavaFX项目运行JavaFX官网文档&#xff1a;https://openjfx.io/openjfx-docs/ JavaFX 2008年12月05日诞生&#xff0c;是一个开源的下一代客户端应用程序平台&#xff0c;适用于基于 Java 构建的桌面、移动和嵌入式系统。这是许多个人和公司的协作努力&#…

函数栈帧的创建和销毁(C语言)

函数栈帧的创建和销毁&#xff08;C语言&#xff09;前言主体前言 函数栈帧是一个非常重要的概念&#xff0c;是重点也是难点&#xff0c;当然涉及底层方面的知识都会很难&#xff0c;但是对我们理解函数的创建和运用有非常重要的作用。本篇博客的目的就是了解函数栈帧的创建和…

go 命令行工具整理

这里会整理可能会使用到的命令行参数&#xff0c;比如 go build、go run&#xff0c;诸如此类。了解这些内容对我们工作会有什么帮助吗&#xff1f;更多的时候&#xff0c;是能让我们理解代码编译的意图&#xff0c;或者&#xff0c;给我们一种排查问题的手段。 比方说&#x…

电子学会2022年12月青少年软件编程(图形化)等级考试试卷(一级)答案解析

目录 一、单选题(共25题&#xff0c;共50分) 二、判断题(共10题&#xff0c;共20分) 三、编程题(共2题&#xff0c;共30分) 青少年软件编程&#xff08;图形化&#xff09;等级考试试卷&#xff08;一级&#xff09; 一、单选题(共25题&#xff0c;共50分) 1. 小明想在开始…

【博学谷学习记录】超强总结,用心分享 | 架构师 Spring源码学习总结

文章目录Spring的循环依赖1.循环依赖的定义&&原因2.循环依赖的场景1.构造器注入引起循环依赖2.Field属性setter注入的循环依赖3.循环依赖解决思路4.三级缓存5.面试题[三级缓存]AOP源码深度剖析概述Spring AOP的前世今生实现机制**JDK 动态代理****CGLIB 代理**流程总结…

六十分之十三——黎明前

目录一、目标二、计划三、完成情况四、提升改进(最少3点)五、意外之喜(最少2点)六、总结一、目标 明确可落地&#xff0c;对于自身执行完成需要一定的努力才可以完成的 1.8本技术管理书籍阅读(使用番茄、快速阅读、最后输出思维导图)2.吴军系列硅谷来信1听书、香帅的北大金融…

成都哪家机构的Java培训比较好,求一个不坑的?

关于这个问题&#xff0c;相信你会得到很多条答案&#xff0c;以及很多家机构的自荐。既然如此&#xff0c;不如也了解一下老牌IT职业教育机构&#xff1a;有足够丰富的教学经验&#xff0c;丰富的教学产品资源以及成熟的就业保障体系&#xff0c;还有就是承担风险的能力。 很…

计算机网络7:传输层相关

目录1-传输层1.1 UDP 和 TCP 的特点1.1.1 UDP用户数据报格式1.1.2 TCP首部格式1.1.2.1 常用端口号1.2 TCP的三次握手1.2.1 三次握手的原因1.3 TCP四次挥手1.3.1 四次挥手的原因1.3.2 TIME_WAIT为什么是2MSL1.4 TCP的可靠传输有效机制1.4.1 TCP可靠传输-超时重传1.4.2 TCP流量控…

封装、继承、Super、重写、多态instanceof类型转换的使用以及个人见解

这里写目录标题封装继承supersuper和this的区别重写多态instanceof类型转换封装 之前我们调用共有的属性&#xff0c;是直接可以调用的 但是属性私有后&#xff0c;无法在直接.调用 只能通过getset调用 继承 super 可以直接调用父类中属性和方法&#xff0c;私有的无法做 其…

TCP详解及面试相关问题

文章目录1、计算机模型2、客户端和服务端通信——TCP协议&#xff08;1&#xff09;socket套接字&#xff08;2&#xff09;TCP三次握手——创建socket&#xff08;3&#xff09;连接的本质&#xff08;4&#xff09;TCP四次挥手——释放socket资源&#xff08;5&#xff09;TC…

如何用PHP实现消息推送

什么是消息推送 通过服务器自动推送消息到客户端(浏览器&#xff0c;APP&#xff0c;微信)的应用技术。 2. 为什么要使用消息推送技术 通常情况下都是用户发送请求浏览器显示用户需要的信息。推送技术通过自动传送信息给用户&#xff0c;来减少用于网络上搜索的时间。它根据…

SSH 服务详解 (八)-- vscode 通过 SSH 远程连接 linux 服务器

vscode 通过 SSH 远程连接 linux 服务器 SSH服务详解(一)–Linux SSH 服务器与客户端的安装与启动 SSH服务详解(二)–使用私钥登录 SSH 服务器(免密登录) SSH 服务详解 (三)-- 使用 SSH 代理 SSH 服务详解 (四)-- 本地调用远程主机的命令 SSH 服务详解 (五)-- 远程文件拷贝…

零信任-微软零信任介绍(2)

微软零信任是什么&#xff1f; Microsoft Zero Trust 是一种安全架构&#xff0c;旨在在没有信任任何设备、用户或网络的情况下保护网络。这种架构使用多重验证和分段技术&#xff0c;以确保每个请求和资源的安全性。 零信任不假定任何内部用户或设备是安全的&#xff…

硬件工程师入门基础知识(一)基础元器件认识(一)

硬件工程师入门基础知识 &#xff08;一&#xff09;基础元器件认识&#xff08;一&#xff09; 今天水一篇hhh。介绍点基础但是实用的东西。 tips&#xff1a;学习资料和数据来自《硬件工程师炼成之路》、百度百科、网上资料。 1.贴片电阻 2.电容 3.电感 4.磁珠 1.贴片电…

Android 基础知识4-2.4程序签名打包

Android APP都需要我们用一个证书对应用进行数字签名&#xff0c;不然的话是无法安装到Android手机上的&#xff0c;平时我们调试运行时到手机上时&#xff0c;是AS会自动用默认的密钥和证书来进行签名&#xff1b;但是我们实际发布编译时&#xff0c;则不会自动签名&#xff0…

IDEA设置只格式化本次迭代变更的代码

趁着上海梅雨季节&#xff0c;周末狠狠更新一下。平常工作在CR的时候&#xff0c;经常发现会有新同事出现大量代码变更行..一看原因竟是在格式化代码时把历史代码也格式化掉了这样不仅坑了自己&#xff08;覆盖率问题等&#xff09;&#xff0c;也可能会影响原始代码责任到人&a…

python 字典的概念叙述和使用方法

文章目录1. 一个简单的字典2. 使用字典2.1 访问字典中的值2.2 添加键-值对2.3 修改字典中的值2.4 删除键-值对3. 遍历字典3.1 遍历所有键-值对3.2 遍历字典中的所有键3.3 按顺序遍历字典中的所有键3.4 遍历字典中的所有值4.嵌套4.1 字典列表4.2 range() 函数4.3 在字典中存储列…

Java中导入、导出Excel——HSSFWorkbook 使用

一、介绍 当前B/S模式已成为应用开发的主流&#xff0c;而在企业办公系统中&#xff0c;常常有客户这样子要求&#xff1a;你要把我们的报表直接用Excel打开(电信系统、银行系统)。或者是&#xff1a;我们已经习惯用Excel打印。这样在我们实际的开发中&#xff0c;很多时候需要…

自动化测试岗位求职简历编写规范+注意事项,让你的简历脱颖而出

目录 前言 1.个人信息 2.教育背景(写最高学历) 3.个人技能(按精通/掌握/熟练/了解层次来写) 4.工作经历 5.工作经验/项目经历 6.自我评价 总结 前言 挑选一个阅读舒适度不错的模板 HR和面试官看的简历多&#xff0c;都是快速阅读&#xff0c;舒适度特别重要&#xff1b…

ctfshow 每周大挑战 极限命令执行

《简单的命令执行题目》 这里感叹一下&#xff0c;g4佬是真好厉害&#xff0c;这次题目十分的难&#xff0c;嗯&#xff0c;对我这种菜鸡来说是这样的&#xff0c;想了一天&#xff0c;最后结束了&#xff0c;也还是没有想明白第五题的解法&#xff0c;我真是fw&#xff0c;到最…