堆栈
-
C++中的栈和堆是用于存储变量和对象的两个主要内存区域。
-
栈是一种自动分配和释放内存的区域,用于存储局部变量和函数调用的上下文。栈上的内存分配和释放是自动进行的,无需手动管理。
-
堆是动态分配内存的区域,用于存储动态创建的对象和数据结构。
-
堆上的内存分配和释放需要手动进行,通过使用 new / malloc 和 delete / free 运算符或者使用智能指针等机制。
-
堆(Heap)
-
堆是在程序运行时动态分配内存的区域,用于存储动态创建的对象和数据结构。
-
在堆上分配的内存需要手动进行管理,通过使用 new 和 delete 运算符或者智能指针等机制进行内存的分配和释放。
-
堆上的内存可以在任何时候进行分配和释放,而不受作用域的限制。
cppint* ptr = new int; // 动态分配一个整型内存块 *ptr = 5; delete ptr; // 释放内存
-
-
栈(tack)
-
栈是基于线程而言的,每条线程都有属于自己的栈区。
-
栈是一种自动分配和释放内存的区域,用于存储局部变量和函数调用的上下文。
-
栈上的内存分配和释放是自动进行的,无需手动管理。
-
栈上的内存分配和释放遵循"先进后出"的原则,即最后进入栈的变量最先离开。
cppvoid foo() { int x = 5; // 在栈上分配整型变量 // ... } // 函数结束,栈上的变量自动释放
-
-
栈上分配的内存特点
- 栈上分配的内存空间相对较小,受限于编译器和操作系统的设置。通常在几兆字节到几十兆字节之间。
- 栈上的内存分配和释放速度较快,仅涉及移动栈指针。
- 栈上的内存分配是按照严格的顺序进行的,无法随机访问。
-
堆和栈的比较
- 堆和栈都是用于存储数据的内存区域,但它们有不同的特点和用途。
- 堆适用于动态分配内存,可以在任何时候进行分配和释放,适用于需要灵活管理内存的情况。
- 栈适用于自动分配和释放内存,适用于局部变量和函数调用的上下文。
内存
-
new
-
动态分配单个对象
-
使用new运算符可以在堆上动态分配单个对象的内存,并返回指向该内存的指针。
-
语法:new 类名; 或 new 类名(参数);
cppint* ptr = new int; // 动态分配一个整型对象 *ptr = 5; // 对分配的内存进行操作 delete ptr; // 释放内存
-
-
底层执行
-
动态分配对象数组:
-
使用new运算符可以在堆上动态分配对象数组的内存,并返回指向该内存的指针。
-
语法:new 类名[数组大小];
cppint* arr = new int[5]; // 动态分配一个包含5个整型元素的数组 for (int i = 0; i < 5; ++i) { arr[i] = i; } delete[] arr; // 释放内存
-
-
-
delete
-
释放单个对象内存:
-
使用delete运算符可以释放通过new运算符分配的单个对象的内存。
-
语法:delete 指针;
cppint* ptr = new int; // 动态分配一个整型对象 *ptr = 5; delete ptr; // 释放内存
-
-
释放对象数组内存:
-
使用delete[]运算符可以释放通过new运算符分配的对象数组的内存。
-
语法:delete[] 指针;
cpp#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语句块来捕获并处理异常。
cpp#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指向同一块内存,并在不再需要时自动释放该内存。
-
创建
cppstd::shared_ptr<int> ptr = std::make_shared<int>(42);
-
引用计数
cppstd::shared_ptr<int> ptr1 = std::make_shared<int>(42); std::shared_ptr<int> ptr2 = ptr1; // 引用计数递增 std::cout << ptr1.use_count() << std::endl; // 输出2,引用计数为2
-
解引用
cppstd::shared_ptr<int> ptr = std::make_shared<int>(42); std::cout << *ptr << std::endl; // 输出42
-
重置指针
cppstd::shared_ptr<int> ptr = std::make_shared<int>(42); ptr.reset(); // 释放资源,引用计数减少 if (ptr == nullptr) { std::cout << "智能指针为空" << std::endl; }
-
-
unique_ptr
-
unique_ptr是一种独占式智能指针,用于唯一地拥有一个对象。它提供了对动态分配的内存的所有权,并在不再需要时自动释放该内存。
-
创建
cppstd::unique_ptr<int> ptr = std::make_unique<int>(42);
-
移动语义
cppstd::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; }
-
解引用
cppstd::unique_ptr<int> ptr = std::make_unique<int>(42); std::cout << *ptr << std::endl; // 输出42
-
释放资源
cppstd::unique_ptr<int> ptr = std::make_unique<int>(42); ptr.release(); // 释放资源,但不销毁指针 if (ptr == nullptr) { std::cout << "unique_ptr已释放资源" << std::endl; }
-