【C++学习笔记】----内存管理(new、delete、malloc、free、内存分布图、各数据所在区域。)

1.常见面试题

1.new和malloc,delete和free的区别?

new和delete,malloc和free
首先new 和 delete是关键字(操作符),而malloc和free是函数。
new会初始化对象,malloc不会。
new根据所需对象的个数,直接开辟空间;malloc需要自己计算字节大小开辟。
new不需要,malloc返回值需要强转成需要的类型。
new开辟失败会抛异常,而malloc会返回NULL。
针对自定义类型new会调用构造函数,delete会调用析构函数,malloc和free不会。

new底层调用operator new函数,operator new底层是Malloc实现,但是多了一个抛异常。(delete类似)

2.malloc,calloc,realloc区别?

malloc按字节开辟大小,不初始化。
calloc和malloc差不多,但是会初始化为0。
realloc扩容,扩容失败返回NULL,扩容成功原来空间自动释放。
在这里插入图片描述
3.如何在堆上申请4G内存?

32位地址空间下不能申请大于0x7fffffff的空间,所以要在64位空间下申请。

4.定位New.
malloc开辟一段空间,未初始化,定位new调用构造,初始化数据成员。
在这里插入图片描述

2.内存分布

在这里插入图片描述

3.代码展示

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
using namespace std;
static int val1 = 1;//.data 数据段	
int val2 = 2;//.data
void test1()
{
	
	static int val3 = 3;//数据段
	int val4 = 4;//栈
	int arr1[10] = { 97,2,3,4 };//栈-数组
	char arr2[] = { 'a','b','c','d','e' };//栈-数组
	char arr3[] = "abcde";//栈-数组
	const char* arr4 = "abcde";//代码段不可以改(确认)
	int* arr5 = (int*)malloc(sizeof(int) * 4);//堆
	int* arr6 = (int*)realloc(arr5, sizeof(int) * 5);//堆
	//cout << "数据段val1->" << &val1 << endl;
	//cout << "数据段val2->" << &val2 << endl;
	//cout << "数据段val3->" << &val3 << endl;
	//cout << "栈val4->" << &val4 << endl;
	//cout << sizeof(val1) << endl;
	//cout << sizeof(val2) << endl;
	//cout << sizeof(val3) << endl;
	//cout << sizeof(val4) << endl;
	//printf("%p\n", arr1);//指向第一个元素
	//printf("%p\n", &arr1+1);//跳过整个数组大小
	//printf("%c\n",*(arr2+1)-32);//B
	//printf("%p\n", arr2);//栈
	//printf("%p\n", arr3);//栈
	//printf("%s\n", arr2);//无\0,烫烫烫
	//printf("%s\n", arr3);//有\0
	//printf("%p\n", &arr3+1);//跳过整个数组大小
	//printf("%s", arr1);
	//printf("%c", *arr1);
	//字符串输出的话,遇到0结束,所以内存中读取时,char读取所以内存中97对应的是a,
	//由于我们数组本来是int类型,所以高位0存在高位,整型截断,直接输出。
	//printf("%p\n", arr4);
	//printf("%s\n", arr4);
	//printf("%p\n", &arr5);//指针的地址在栈
	//printf("%p\n", &arr5+1);//指针的地址在栈+1-》+4
	//printf("%p\n", arr5);//指针指向的空间在堆
	//printf("%p\n", arr5+1);//指针指向的空间在堆
	//printf("%p\n", &arr6);//指针的地址在栈
	//printf("%p\n", arr6);//指针指向的空间在堆



	//cout << sizeof(arr1) << endl;//40
	//cout << sizeof(arr2) << endl;//5数组
	//cout << sizeof(arr3) << endl;//6数组
	//cout << sizeof(arr4) << endl;//4指针
	//cout << sizeof(arr5) << endl;//4指针
	//cout << sizeof(arr6) << endl;//4指针


	//cout << strlen(arr2) << endl;//不确定,取决于后面空间0的位置
	//cout << strlen(arr3) << endl;//5
	//cout << strlen(arr4) << endl;//5
}
class A
{
public:
	A()
	{
		cout << "A()" << endl;
	}
	~A()
	{
		cout << "~A()" << endl;
	}
};
void test2()
{
	/*int* arr1 = (int*)malloc(sizeof(int) * 10);
	free(arr1);
	int* arr2 = new int[10];
	delete arr2;*/

	A* a1 = (A*)malloc(sizeof(A) * 10);
	free(a1);
	A* a2 = new A[10];//自定义类型调用构造和析构
	delete[] a2;

}
void test3()
{
	void* p = new char[0xffffffff];//64位下
	cout << "new:" << p << endl;


}
void test4()
{
	int* arr1 = (int*)malloc(sizeof(int) * 10);
	int* arr2 = (int*)calloc(10, sizeof(int));
	int* arr3 = (int*)realloc(arr1,0x6fffffff);
	cout << arr1 << endl;
	cout << arr2 << endl;
	cout << arr3 << endl;
	cout << arr1 << endl;
}
void test5()
{
	A* a1 = (A*)malloc(sizeof(A) * 10);
	new(a1) A;
	delete A;
}
int main()
{
	//test1();
	//test2();
	//test3();
	//test4();
	//test5();
	system("pause");
	return 0;
}

4.总结分析

(1).sizeof字节大小,32位下指针都是4字节,如果是数组名,计算的是整个数组大小。
在这里插入图片描述
(2).“abc”=3,后面有隐含的\0。所以char arr4 []=“abc” sizeof(arr4)=4,strlen是以\0为标志结束,所以长度是3,后面会有一个\0;{a,b,c}没有,strlen就不能计算它的长度了。

(3).全局变量,静态变量在数据区,临时变量局部变量在栈区,动态开辟的区域在堆区(*arr),(arr)即(&arr)在栈区,不可以改常量、函数在代码段。

(4).val1、val2,全局变量。初始化在main函数之前,val2(全局)所有文件可见,val1(静态全局)当前文件可见,链接属性不同。
而val3静态局部变量只能在当前作用域使用,运行到它才初始化。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章