【C++】内存管理

简介: 【C++】内存管理

前言:在前面很长一段时间我们都在学习类和对象这块地方,今天我们将进一步的学习内存管理,为后面将要学习的内容做铺垫。

d6dc0126edd141a985d72de501ef756b.jpg


内存管理

这里我们先来回顾一下前面学习C语言所了解内存分配的区域:

C/C++的内存分配主要分为以下几个区域:

  1. 栈(Stack):栈是由编译器自动分配和释放的内存区域,用于存储局部变量函数参数函数调用的上下文信息。栈的分配和释放都是自动的,遵循"后进先出"(LIFO)的原则。
  2. 堆(Heap):堆是由程序员手动分配和释放的内存区域,用于存储动态分配的对象。堆的内存分配和释放必须由程序员显式地调用newdeletemallocfree等函数来进行。
  3. 全局变量区(Global Data Area):全局变量区也称为静态数据区,用于存储全局变量和静态变量。全局变量在程序运行期间一直存在,直到程序结束才被释放。
  4. 常量区(Constant Data Area):常量区用于存储常量数据,如字符串字面量和常量全局变量。该区域的数据在程序运行期间不可修改。
  5. 代码区(Code Area):代码区存储程序的可执行代码,包括函数体和指令。该区域通常是只读

的。

需要注意的是,不同的编译器和操作系统可能对内存的管理方式有所不同。因此,在编写跨平台的C/C++程序时,应当遵循标准的内存分配和释放规则,避免依赖于特定编译器或操作系统的行为。


C语言的内存管理方式

动态分配是在程序运行时根据需要手动分配和释放的内存空间。动态分配使用malloc、calloc或realloc函数动态申请内存空间,并使用free函数释放已分配的内存空间。动态分配的内存可以在函数之间共享,并且可以灵活地调整大小。但需注意,在使用动态分配的内存之后需要手动释放,否则会导致内存泄漏。关于这部分不是今天的重点,因此如果有不懂的地方可以参考我之前的博客C语言动态内存管理。

C++的内存管理方式

C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符进行动态内存管理。

newdelete操作符:new操作符用于在堆上分配内存,delete操作符用于释放分配的内存。

new操作符详解

  1. 开辟一块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类型的空间

  1. 开辟一块具有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++中的两个自定义内存管理函数。它们可以重载,用于自定义对象的内存分配和释放。

  1. 重载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;
}
  1. 重载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,类和对象就在这里和大家告一段落了,各位加油呐!


结语:今天的内容就到这里吧,谢谢各位的观看,如果有讲的不好的地方也请各位多多指出,作者每一条评论都会读的,谢谢各位。


相关文章
|
6天前
|
存储 编译器 C语言
【C++】C\C++内存管理
【C++】C\C++内存管理
【C++】C\C++内存管理
|
5天前
|
编译器 C++
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
virtual类的使用方法问题之C++类中的非静态数据成员是进行内存对齐的如何解决
|
7天前
|
存储 Java C语言
【C++】C/C++内存管理
【C++】C/C++内存管理
|
11天前
|
存储 编译器 C语言
C++内存管理(区别C语言)深度对比
C++内存管理(区别C语言)深度对比
40 5
|
26天前
|
NoSQL Redis C++
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
c++开发redis module问题之在复杂的Redis模块中,特别是使用第三方库或C++开发时,接管内存统计有哪些困难
|
1月前
|
存储 C语言 C++
【C/C++】动态内存管理( C++:new,delete)
C++的`new`和`delete`用于动态内存管理,分配和释放内存。`new`分配内存并调用构造函数,`delete`释放内存并调用析构函数。`new[]`和`delete[]`分别用于数组分配和释放。不正确匹配可能导致内存泄漏。内置类型分配时不初始化,自定义类型则调用构造/析构。`operator new`和`operator delete`是系统底层的内存管理函数,封装了`malloc`和`free`。定位`new`允许在已分配内存上构造对象,常用于内存池。智能指针等现代C++特性能进一步帮助管理内存。
|
1月前
|
存储 编译器 程序员
【C/C++】动态内存管理(C:malloc,realloc,calloc,free)
探索C++与C语言的动态内存管理:从malloc到new/delete,了解内存分布及栈、堆的区别。文章涵盖malloc、realloc、calloc与free在C中的使用,强调内存泄漏的风险。C++引入new和delete,支持对象构造与析构,还包括operator new和placement-new。深入分析内存管理机制,揭示C与C++在内存处理上的异同。别忘了,正确释放内存至关重要!
|
1月前
|
算法 Java C++
C++和Python在内存管理上的主要区别是什么?
【7月更文挑战第2天】C++和Python在内存管理上的主要区别是什么?
61 1
|
1月前
|
安全 算法 编译器
C++一分钟之-内存模型与数据竞争
【7月更文挑战第10天】了解C++11内存模型对多线程编程至关重要。它定义了线程间同步规则,包括顺序一致性、原子操作和内存屏障。数据竞争可能导致不确定行为,如脏读和丢失更新。可通过互斥量、原子操作和无锁编程避免竞争。示例展示了`std::mutex`和`std::atomic`的使用。掌握内存模型规则,有效防止数据竞争,确保多线程安全和性能。
35 0
|
1月前
|
存储 Java 程序员
Python和C++在内存管理方面有什么不同?
【7月更文挑战第2天】Python和C++在内存管理方面有什么不同?
24 0