1. 内存分配和释放的方式
C++中的内存主要分为 栈内存 和 堆内存。
栈内存
栈内存由编译器自动管理。局部变量、函数参数等都在栈上分配,离开作用域时自动释放。
void function() {
int a = 10; // 分配在栈上
// 当函数结束时,a自动释放
}
堆内存
堆内存需要手动管理,使用 new
操作符进行分配,用 delete
操作符进行释放。如果忘记释放,会造成 内存泄漏,即程序不再需要的内存没有正确释放。
void function() {
int* p = new int; // 分配在堆上
*p = 10;
delete p; // 释放内存
}
2. 使用new
和delete
new
用于分配单个对象或数组。
int* p = new int(10); // 分配一个int并初始化为10
int* arr = new int[100]; // 分配一个含有100个整数的数组
delete
用于释放单个对象,delete[]
用于释放数组。
delete p; // 释放单个对象
delete[] arr; // 释放数组
3. 常见的内存分配和释放错误
1. 忘记释放内存(内存泄漏)
void function() {
int* p = new int(10);
// 忘记 delete p; 导致内存泄漏
}
2. 重复释放(双重释放)
void function() {
int* p = new int(10);
delete p;
delete p; // 再次删除同一指针会导致未定义行为
}
3. 使用已释放的内存(悬空指针)
void function() {
int* p = new int(10);
delete p;
*p = 20; // 悬空指针,使用已释放的内存,导致未定义行为
}
4. 没有匹配使用new[]
和delete[]
void function() {
int* arr = new int[100];
delete arr; // 错误,应该使用 delete[] arr;
}
5. 没有匹配使用new
和delete
void function() {
int* p = new int(10);
delete[] p; // 错误,应该使用 delete p;
}
4. 智能指针(Smart Pointers)
为了更好地管理内存,C++11引入了智能指针,它们在适当的时候自动释放内存,从而减少手动管理内存的复杂性和可能出现的错误。
std::unique_ptr
:一个对象只能有一个唯一的智能指针拥有。
#include <memory>
void function() {
std::unique_ptr<int> p = std::make_unique<int>(10);
// p 出作用域时,内存自动释放
}
std::shared_ptr
:多个智能指针可以共享同一个对象。
#include <memory>
void function() {
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::shared_ptr<int> p2 = p1; // p1和p2共享同一个对象
// p1和p2出作用域并且引用计数为0时,内存自动释放
}
std::weak_ptr
:一种不影响引用计数的智能指针,通常用于避免循环引用。
#include <memory>
void function() {
std::shared_ptr<int> p1 = std::make_shared<int>(10);
std::weak_ptr<int> wp = p1; // wp 不增加引用计数
// 需要使用 wp.lock() 来获取 std::shared_ptr
}
5. 自定义内存管理
有时可能需要自定义内存管理,如重载 new
和 delete
操作符。
class MyClass {
public:
void* operator new(size_t size) {
std::cout << "Custom new" << std::endl;
return ::operator new(size);
}
void operator delete(void* p) {
std::cout << "Custom delete" << std::endl;
::operator delete(p);
}
};
int main() {
MyClass* p = new MyClass();
delete p;
return 0;
}
总结
- 栈内存:自动管理,离开作用域时自动释放。
- 堆内存:手动管理,使用
new
分配,delete
释放。 - 智能指针:自动管理堆内存,减少内存释放错误。
- 常见错误:内存泄漏、双重释放、悬空指针、匹配错误。
通过理解和正确应用这些内存管理技术,可以大大降低内存相关错误,写出健壮的C++程序。