前言:在前面很长一段时间我们都在学习类和对象这块地方,今天我们将进一步的学习内存管理,为后面将要学习的内容做铺垫。
内存管理
这里我们先来回顾一下前面学习C语言所了解内存分配的区域:
C/C++的内存分配主要分为以下几个区域:
- 栈(Stack):栈是由编译器自动分配和释放的内存区域,用于存储局部变量、函数参数和函数调用的上下文信息。栈的分配和释放都是自动的,遵循"后进先出"(LIFO)的原则。
- 堆(Heap):堆是由程序员手动分配和释放的内存区域,用于存储动态分配的对象。堆的内存分配和释放必须由程序员显式地调用new和delete或malloc和free等函数来进行。
- 全局变量区(Global Data Area):全局变量区也称为静态数据区,用于存储全局变量和静态变量。全局变量在程序运行期间一直存在,直到程序结束才被释放。
- 常量区(Constant Data Area):常量区用于存储常量数据,如字符串字面量和常量全局变量。该区域的数据在程序运行期间不可修改。
- 代码区(Code Area):代码区存储程序的可执行代码,包括函数体和指令。该区域通常是只读
的。
需要注意的是,不同的编译器和操作系统可能对内存的管理方式有所不同。因此,在编写跨平台的C/C++程序时,应当遵循标准的内存分配和释放规则,避免依赖于特定编译器或操作系统的行为。
C语言的内存管理方式
动态分配是在程序运行时根据需要手动分配和释放的内存空间。动态分配使用malloc、calloc或realloc函数动态申请内存空间,并使用free函数释放已分配的内存空间。动态分配的内存可以在函数之间共享,并且可以灵活地调整大小。但需注意,在使用动态分配的内存之后需要手动释放,否则会导致内存泄漏。关于这部分不是今天的重点,因此如果有不懂的地方可以参考我之前的博客C语言动态内存管理。
C++的内存管理方式
C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。
new和delete操作符:new操作符用于在堆上分配内存,delete操作符用于释放分配的内存。
new操作符详解
- 开辟一块int类型的空间,让指针指向这块空间
int* buffer1 = new int;//new一个int类型的空间
2. 开辟一块int类型的空间并初始化为10,让指针指向这块空间
int* buffer2 = new int(10);// new一个int类型的空间并初始化为10
3. 开辟一块具有10个int类型的空间,让指针指向这块空间
int* buffer3 = new int[10];// new10个int类型的空间
- 开辟一块具有10个int类型的空间并且对其初始化(未初始化的部分自动初始化成0),让指针指向这块空间.
nt* buffer4 = new int[10]{ 10,9,8,7,6,5 }; //跟数组的初始化很像,大括号有几个,初始化几个,其余为0。不过C++11才支持的语法
delete操作符详解
delete buffer; // 释放指针p所指向的内存空间
当使用new操作符分配了一个数组时,应使用delete[]操作符释放内存空间,例如:
int* arr = new int[10]; // 分配一个int类型的数组 // 使用arr delete[] arr; // 释放数组内存空间
new / delete 操作自定义类型
结论:
申请空间时:malloc只开空间,new既开空间又调用构造函数初始化。
释放空间时:delete会调用析构函数,free不会.
实例演示:
class Myclass { public: Myclass()//默认构造 { cout << "默认构造" << i <<endl; i++; } ~Myclass()//析构 { cout << "析构函数" << x <<endl; x++; } private: static int x; static int i; }; int Myclass::x = 0; int Myclass::i = 0; int main() { Myclass* p1 = new Myclass; delete p1; return 0; }
实例演示:
class Myclass { public: Myclass()//默认构造 { cout << "默认构造" << i <<endl; i++; } ~Myclass()//析构 { cout << "析构函数" << x <<endl; x++; } private: static int x; static int i; }; int Myclass::x = 0; int Myclass::i = 0; int main() { Myclass* p2 = new Myclass[10]; delete[]p2; return 0; }
总结:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与free不会,并且malloc如若开辟内存失败,会返回空指针这个我们都晓得的,但是new失败会抛异常
operator new与operator delete函数
new和delete是用户进行动态内存申请和释放的操作符,operator new 和operator delete是系统提供的全局函数,new在底层调用operator new全局函数来申请空间,delete在底层通过operator delete全局函数来释放空间。
"operate new"和"operate delete"是C++中的两个自定义内存管理函数。它们可以重载,用于自定义对象的内存分配和释放。
- 重载operator new函数:通过重载operator new函数,可以自定义对象在内存中的分配方式。其语法为:
void* operator new(size_t size);
operator new函数接受一个size_t类型的参数,表示要分配的内存大小,返回一个void类型的指针,指向分配的内存空间。可以在函数内部使用标准的内存分配函数(如malloc)或其他自定义的分配方式。
示例:
void* operator new(size_t size) { void* p = malloc(size); // 使用malloc函数分配内存 if (!p) { throw std::bad_alloc(); // 内存分配失败,抛出异常 } return p; }
- 重载operator delete函数:通过重载operator delete函数,可以自定义对象的内存释放方式。其语法为:
void operator delete(void* ptr);
operator delete函数接受一个void类型的指针作为参数,表示要释放的内存空间。可以在函数内部使用标准的内存释放函数(如free)或其他自定义的释放方式。
示例:
void operator delete(void* ptr) { free(ptr); // 使用free函数释放内存 }
通过重载operator new和operator delete函数,可以实现对内存分配和释放的个性化控制。这在一些特殊情况下非常有用,例如实现内存池、内存统计等功能。需要注意的是,重载的operator new和operator delete函数必须在对应的类内使用static关键字进行声明。
好啦,今天的内容就到这里啦,下期内容预告STL与string,类和对象就在这里和大家告一段落了,各位加油呐!
结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。