在c++中,内存管理是一个重要的主题,涉及到如何分配和释放内存。以下是一些关键概念和方法。
1.内存管理
C++ 程序的内存通常分为以下几个部分:
- 栈(Stack):用于存储局部变量,函数调用时自动分配和释放。
- 用途:用于存储局部变量和函数调用相关的数据(如函数参数,返回地址等)。
- 特点:
- 先入后出,后入先出
- 自动分配和释放内存
- 内存分配效率高,但容量有限。
- 示例:
void func(){ int x = 10; //x存储栈中 } - 堆(Heap):用于动态分配内存,需手动管理。
- 用途:用于自动分配内存,程序运行时手动申请和释放。
- 特点:
- 需要使用
new或malloc分配内存,使用delete或free释放内存。 - 容量大,但管理复杂,容易导致内存泄漏。
- 需要使用
- 示例
int* ptr = new int(10);//动态分配内存; delete ptr; //手动释放内存 - 全局/静态区:存储全局变量和静态变量。
- 用途:存储全局变量和静态变量。
- 特点:
- 程序运行期间一直存在,直到程序结束时释放。
- 全局变量在整个程序中可见,静态变量在声明的作用域内可见。
- 示例:
int globalVar = 10; //全局变量 void func(){ static int staticVar=20; //局部变量 } - 代码区:存储程序的可执行程序。
- 用途:存储程序的可执行代码。
- 特点:
- 通常只读,防止代码被意外修改。
- 包含函数的机器指令。
- 示例:
void func(){ //函数的机器指存储在代码区 }
2.动态内存分配
C++ 提供了new和 delete 操作符用于动态分配和释放内存:
int* ptr = new int;//分配一个整数
*ptr = 10;//使用分配的内存
detele ptr;//释放内存
对于数组:
int* arr = new int[5]; //分配一个整数数据
delete[] arr; //释放数组内存
3.常见问题
- 内存泄漏:动态分配的内存未释放。
- 悬空指针:释放内存后继续使用指针。
- 双重释放:对同一块内存调用多次
detete
4.智能指针
C++11引入智能指针(如std::unique_ptr和std::shared_ptr),可以自动管理内存,减少手动释放风险:
#include <memory>
std::unique_ptr<int> ptr = std::unique_ptr(10);
4.1 std::unique_ptr
std::unique_ptr是一种独占所有权的智能指针,确保同一时间只有一个智能可以拥有该内存。它在超出作用域时自动释放内存。
void example(){
std::unique_ptr<int> uptr =std::make_unique<int>(5);//使用uptr
}//uptr 超出作用域,内存自动释放
4.2 std::shared_ptr
std::shared_ptr允许多个指针共享同一块内存。它使用引用计数来管理内存,当最后一个指针超出作用域时,内存才会被释放。
void exampe(){
std::shared_ptr<int> sptr1 =std::make_shared<int>(10);
std::stared_ptr<int> sptr2 = sptr1;//sptr1和sptr2共享同一块内存
}//当 sptr1 和 sptr2 超出作用域,内存自动释放
4.2.1 std::make_shared的使用
std::make_shared是个工厂函数,用于创建std::shared_ptr对象。它比直接使用std::shared_ptr构造函数更高级,因为他只分配一次内存,同时存储对象和控制块。
#include <memory>
#include <iostream>
class MyClass{
public:
MyClass(int value) : value_(value){
std::cout << "MyClass constructed with value:" << value << std::endl;
}
~MyClass(){
std::cout << "MyClass destroyed with value:" << value_ << std::endl;
}
int getValue() const {return value_;}
private:
int value_;
};
int main(){
//使用std::make_shared 创建 shared_ptr
auto ptr = std::make_shared<MyClass>(42);
std::cout << "Value:"<< ptr->getValue() << std::endl;
return 0;
}
使用std::make_shared的优点:
1.更高效:只分配一次内存,同时存储对象和控制块
2.更安全:避免了内存泄漏的风险
3.更简洁:代码更易读和维护
4.3 std::weak_ptr
std::weak_ptr是与std::shared_ptr配合使用的智能指针,用于解决循环引用的问题。它补增加引用计数。
void example(){
std::shared_ptr<int> sptr = std::make_shared<int>(20);
std::weak_ptr<int> wptr = sptr;//wptr 不增加引用计数
}
通过合理使用智能指针,可以有效避免内存管理中的常见问题。
5.内存对齐
内存对齐是为了提高访问效率,编译器可能会在分配内存时插入填充字节。
6.调试工具
使用工具(如 Valgrind)可以检查内存泄漏和其他内存问题。
通过合理使用动态内存和智能指针,可以有效避免内存管理中的常见问题。

622

被折叠的 条评论
为什么被折叠?



