C++内存管理与模版(用法详解)

本文详细介绍了C++中不同内存区域(内核空间、栈、堆、数据段等)的划分,以及new和delete操作符的工作原理,涵盖了全局变量、静态变量、数组、构造函数和析构函数,以及函数和类模板的实例化。
摘要由CSDN通过智能技术生成
  • C/C++中程序内存区域划分

  1. 内核空间(用户代码不能读写)
  2. 栈(函数中存放的变量)
  3. 内存映射段
  4. 堆(重点)
  5. 数据段(静态区)全局变量 / 静态变量
  6. 代码段(常量区)

试分析下列代码

int globalVar = 1;// 这个变量globalVar 存放在静态区(原因:globalVar是全局变量)

static int staticGlobalVar = 1;//静态区   是静态变量

void Test()

{

static int staticVar = 1;//静态区,静态变量

int localVar = 1;// 栈区

int num1[10] = {1, 2, 3, 4};//num1存放在栈区,*num1存放在栈区

char char2[] = "abcd";//char2存放在栈区,*char2存放在栈区

这段代码是将"abcd"拷贝下来,开辟空间,放置在栈区

const char* pChar3 = "abcd";//PChar3存放在栈区,*pChar3存放在常量区

//这里解释一下pChar3 pChar3是const char* ,所指向的内容不能被修改

   这段代码可以说明s存放的位置与t存放的位置一样

int* ptr1 = (int*)malloc(sizeof (int)*4);//ptr1存放在栈区,*ptr1存放在堆区

int* ptr2 = (int*)calloc(4, sizeof(int));//与上面同理

int* ptr3 = (int*)realloc(ptr2, sizeof(int)*4);//与上面同理

free (ptr1);

free (ptr3);

}

  • C++中的new和delete(操作符)

C语言向堆上申请空间,使用malloc  realloc  calloc申请空间,放回首地址

C++使用new申请堆上的空间,返回首地址

new的好处

  1. 简洁
  2. 可以控制初始化
  3. 对于自定义类型,自动调构造函数
  4. 申请失败,会抛异常,无需手动检查

申请内置类型

#include<iostream>
using namespace std;
int main()
{
    int* t = new int(1);//申请一个整形,并且将这个整形赋值为1
    cout << *t << endl;

    delete t;//释放这块空间
    return 0;
}

申请内置类型数组

#include<iostream>
using namespace std;
int main()
{
    int* arr = new int[10] { 1 };//申请10个整形的空间,第一个值赋为1,其余赋为0
    delete[] arr;//释放空间
    return 0;
}

申请自定义类型

下面演示抛异常:

#include <iostream>
using namespace std;
void func()
{
	while (1)
	{
		int* temp = new int[1024 * 1024 * 100];
		cout << temp << endl;
	}
}
int main()
{
	try
	{
		func();
	}
	catch (const exception& e)
	{
		cout << e.what() << endl;
	}
	return 0;
}

new的原理分析:

(这里不展开细讲,如果想知道其中细节,请在评论区私信我)

首先明确new是一个操作符,它是一个又operator new重载的运算符函数

operator new又是对malloc进行封装的函数

delete同样如此

delete的底层是operator delete

operator delete 的底层是free

定位new

显示调用构造函数,对一块已经有的空间初始化

使用方式 new ( 类的指针变量 ) 类名 (构造函数初始化的值)

举个例子:

#include <iostream>
using namespace std;
class A
{
public:
	A(int a = 1 , int b = 2 )
	{
		_a = a;
		_b = b;
	}
	void print()
	{
		cout << _a << " " << _b << endl;
	}
private:
	int _a;
	int _b;
};
int main()
{
	A* p = new A;
	new(p)A(3,3);
	p->print();
	return 0;
}

函数模版

函数模版格式:

template <  typename T1 , typename T2 ....... >

放回值类型 函数名 (参数列表)

#include <iostream>
using namespace std;
template <typename T>
void Swap( T& p1,  T& p2)
{
	T tmp = p1;
	p1 = p2;
	p2 = tmp;
}
int main()
{
	int a = 1;
	int b = 2;
	Swap(a, b);//这里编译器会自动推断出T为int
	cout << a << " " << b << endl;
	return 0;
}

如何强制生成T为一个已知类型的函数

也就是显示实例化

在函数名与参数列表间加一个<T>(T为类型)

#include<iostream>
using namespace std;
template<typename T>
T Add(const T& p1, const T& p2)
{
	return p1 + p2;
}
int main()
{
	int a = 1;
	double b = 2.2;
	Add<int>(a, b);
	return 0;
}

类模版

#include <iostream>
using namespace std;
template<typename T>
class Stack
{
public:
	Stack()
	{}
	~Stack()
	{
		delete[] _arr;
		_size = 0;
		_top = 0;
		_arr = nullptr;
	}
	void PushBack();
private:
	T* _arr = new T[4];
	int _size = 0;
	int _top = -1;
};
template<typename T>
void Stack<T>::PushBack()// 这里Stack<T>是类型名
{
	;
}
int main()
{
    //同一个模版实例化两个对象
	Stack<int> p1;// int类型的对象
	Stack<double> p2; //double类型的对象
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值