C/C++ - 内存管理(C++)

堆栈

  • C++中的栈和堆是用于存储变量和对象​​的两个主要内存区域。
  • 栈是一种自动分配和释放内存的区域,用于存储局部变量和函数调用的上下文。栈上的内存分配和释放是自动进行的,无需手动管理。
  • 堆是动态分配内存的区域,用于存储动态创建的对象和数据结构。
  • 堆上的内存分配和释放需要手动进行,通过使用 new / malloc​​ 和 delete / free​​ 运算符或者使用智能指针等机制。
  • 堆(Heap)

    • 堆是在程序运行时动态分配内存的区域,用于存储动态创建的对象和数据结构。

    • 在堆上分配的内存需要手动进行管理,通过使用 new​​​ 和 delete​​​ 运算符或者智能指针​​等机制进行内存的分配和释放。

    • 堆上的内存可以在任何时候进行分配和释放,而不受作用域的限制。

      int* ptr = new int;  // 动态分配一个整型内存块
      *ptr = 5;
      delete ptr;  // 释放内存
      
  • 栈(tack)

    • 栈是基于线程而言的,每条线程都有属于自己的栈区。

    • 栈是一种自动分配和释放内存的区域,用于存储局部变量和函数调用的上下文。

    • 栈上的内存分配和释放是自动进行的,无需手动管理。

    • 栈上的内存分配和释放遵循“先进后出”的原则,即最后进入栈的变量最先离开。

      void foo() 
      {
          int x = 5;  // 在栈上分配整型变量
          // ...
      }  // 函数结束,栈上的变量自动释放
      
  • 栈上分配的内存特点

    • 栈上分配的内存空间相对较小,受限于编译器和操作系统的设置。通常在几兆字节到几十兆字节之间。
    • 栈上的内存分配和释放速度较快,仅涉及移动栈指针。
    • 栈上的内存分配是按照严格的顺序进行的,无法随机访问。
  • 堆和栈的比较

    • 堆和栈都是用于存储数据的内存区域,但它们有不同的特点和用途。
    • 堆适用于动态分配内存,可以在任何时候进行分配和释放,适用于需要灵活管理内存的情况。
    • 栈适用于自动分配和释放内存,适用于局部变量和函数调用的上下文。

内存

  • new

    • 动态分配单个对象

      • 使用new​​​​运算符可以在堆上动态分配单个对象的内存,并返回指向该内存的指针。

      • 语法:new 类名;​​​​ 或 new 类名(参数);​​​​

        int* ptr = new int;  // 动态分配一个整型对象
        *ptr = 5;  // 对分配的内存进行操作
        delete ptr;  // 释放内存
        
    • 底层执行

    • 动态分配对象数组:

      • 使用new​​​​运算符可以在堆上动态分配对象数组的内存,并返回指向该内存的指针。

      • 语法:new 类名[数组大小];​​​​

        int* arr = new int[5];  // 动态分配一个包含5个整型元素的数组
        for (int i = 0; i < 5; ++i) 
        {
            arr[i] = i;
        }
        delete[] arr;  // 释放内存
        
  • delete

    • 释放单个对象内存:

      • 使用delete​​运算符可以释放通过new​​运算符分配的单个对象的内存。

      • 语法:delete 指针;​​

        int* ptr = new int;  // 动态分配一个整型对象
        *ptr = 5;
        delete ptr;  // 释放内存
        
    • 释放对象数组内存:

      • 使用delete[]​​运算符可以释放通过new​​运算符分配的对象数组的内存。

      • 语法:delete[] 指针;​​

        #include <iostream>
        
        
        int main()
        {
        	//new    - malloc
        	//delete - free
        
        	//C
        	int* p1 = (int*)malloc(sizeof(int));
        	if (p1)
        	{
        		free(p1);
        		p1 = NULL;
        	}
        
        	int* p2 = (int*)malloc(sizeof(int) * 10);
        	if (p2)
        	{
        		free(p2);
        		p2 = NULL;
        	}
        
        	//CPP
        	int* p3 = new int;
        	if (p3)
        	{
        		delete p3;
        		p3 = NULL;
        	}
        
        	int* p4 = new int(10);
        	if (p4)
        	{
        		delete p4;
        		p4 = NULL;
        	}
        
        	int* p5 = new int[10];
        	if (p5)
        	{
        		delete[] p5;
        		p5 = NULL;
        	}
        
        	return 0;
        }
        
  • 内存失败处理

    • 在使用new​​运算符分配内存时,如果内存不足或分配失败,会抛出std::bad_alloc​​异常。因此,需要在代码中适当处理异常情况

    • 可以使用try-catch​​语句块来捕获并处理异常。

      #include <iostream>
      
      
      void Exception_CPP()
      {
      	try
      	{
      		//可能会出现错误的代码
      		long long* p = new long long[0xFFFFFFF];
      		delete[] p;
      	}
      	catch (const std::exception& Error)
      	{
      		//出现异常捕获处理异常
      		std::cout << "Exception ->" << Error.what() << std::endl;
      	}
      
      }
      
      int main()
      {
      	Exception_CPP();
      
      	return 0;
      }
      

智能指针

  • 在C++中,智能指针是一种用于管理动态分配的内存资源的工具。它们以对象的形式封装了原始指针,并提供了自动化的内存管理和资源释放,从而减少内存泄漏和悬挂指针等问题。
  • 智能指针主要有两种类型:shared_ptr​​和unique_ptr​​。
  • ​shared_ptr

    • ​shared_ptr​​是一种引用计数智能指针,用于多个指针共享同一个对象。它会跟踪有多少个shared_ptr​​指向同一块内存,并在不再需要时自动释放该内存。

    • 创建

      • std::shared_ptr<int> ptr = std::make_shared<int>(42);
        
    • 引用计数

      • std::shared_ptr<int> ptr1 = std::make_shared<int>(42);
        std::shared_ptr<int> ptr2 = ptr1; // 引用计数递增
        
        std::cout << ptr1.use_count() << std::endl; // 输出2,引用计数为2
        
    • 解引用

      • std::shared_ptr<int> ptr = std::make_shared<int>(42);
        std::cout << *ptr << std::endl; // 输出42
        
    • 重置指针

      • std::shared_ptr<int> ptr = std::make_shared<int>(42);
        ptr.reset(); // 释放资源,引用计数减少
        
        if (ptr == nullptr) {
            std::cout << "智能指针为空" << std::endl;
        }
        
  • ​​unique_ptr

    • ​​unique_ptr​​是一种独占式智能指针,用于唯一地拥有一个对象。它提供了对动态分配的内存的所有权,并在不再需要时自动释放该内存。

    • 创建

      • std::unique_ptr<int> ptr = std::make_unique<int>(42);
        
    • ​​移动语义​

      • std::unique_ptr<int> ptr1 = std::make_unique<int>(42);
        std::unique_ptr<int> ptr2 = std::move(ptr1); // 移动语义,ptr1不再拥有资源
        
        if (ptr1 == nullptr) 
        {
            std::cout << "ptr1不再拥有资源" << std::endl;
        }
        
    • 解引用

      • std::unique_ptr<int> ptr = std::make_unique<int>(42);
        std::cout << *ptr << std::endl; // 输出42
        
    • 释放资源

      • std::unique_ptr<int> ptr = std::make_unique<int>(42);
        ptr.release(); // 释放资源,但不销毁指针
        
        if (ptr == nullptr) 
        {
            std::cout << "unique_ptr已释放资源" << std::endl;
        }
        

相关推荐

  1. C/C++——内存管理

    2024-01-30 00:42:02       37 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-30 00:42:02       16 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-30 00:42:02       16 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-30 00:42:02       15 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-30 00:42:02       18 阅读

热门阅读

  1. 三:C语言-输入与输出

    2024-01-30 00:42:02       29 阅读
  2. Kafka建立生产者消费者

    2024-01-30 00:42:02       28 阅读
  3. springboot 动态导出pdf

    2024-01-30 00:42:02       34 阅读
  4. leetcode 栈和队列相关题目

    2024-01-30 00:42:02       36 阅读
  5. 牛客周赛round30D题讲解(公式推导)

    2024-01-30 00:42:02       37 阅读
  6. 力扣0100——相同的树

    2024-01-30 00:42:02       39 阅读
  7. 代码随想录算法训练营|day15二叉树相关推荐

    2024-01-30 00:42:02       32 阅读
  8. 无人机组装的材料

    2024-01-30 00:42:02       32 阅读
  9. Sentinel背后的原理:守卫你的代码安全之旅

    2024-01-30 00:42:02       43 阅读
  10. MySQL事务和锁04

    2024-01-30 00:42:02       31 阅读
  11. 虾皮API助力电商行业高效商品管理

    2024-01-30 00:42:02       37 阅读
  12. 远程方法调用Remote Method Invocation

    2024-01-30 00:42:02       26 阅读