目录
2. RAII(Resource Acquisition Is Initialization)
动态内存管理是 C++ 编程中的一个重要方面,它允许程序在运行时分配和释放内存。动态内存通常用于那些大小或数量在程序运行时未知的数据结构,如动态数组、链表等。在 C++ 中,动态内存管理主要通过 new
和 delete
操作符来实现。
动态内存分配
使用 new
new
操作符用于在堆上分配内存,并返回指向所分配内存的指针。如果分配失败,new
会抛出一个 std::bad_alloc
异常。
示例:分配单个对象
cpp
深色版本
#include <iostream>
using namespace std;
int main() {
int* ptr = new int; // 分配一个 int 对象的内存
*ptr = 10; // 给指针指向的内存赋值
cout << "Value: " << *ptr << endl; // 输出 Value: 10
delete ptr; // 释放内存
return 0;
}
分配数组
new[]
操作符用于分配数组的内存。同样地,如果分配失败,new[]
也会抛出 std::bad_alloc
异常。
示例:分配整型数组
cpp
深色版本
#include <iostream>
using namespace std;
int main() {
int size = 5;
int* array = new int[size]; // 分配一个 int 数组的内存
for (int i = 0; i < size; ++i) {
array[i] = i * 2; // 给数组元素赋值
}
for (int i = 0; i < size; ++i) {
cout << "array[" << i << "]: " << array[i] << endl; // 输出数组元素
}
delete[] array; // 释放数组内存
return 0;
}
动态内存释放
使用 delete
delete
操作符用于释放先前通过 new
分配的内存。对于非数组对象,使用 delete
;对于数组对象,使用 delete[]
。
示例:释放单个对象
cpp
深色版本
#include <iostream>
using namespace std;
int main() {
int* ptr = new int;
*ptr = 10;
delete ptr; // 释放内存
return 0;
}
示例:释放数组
cpp
深色版本
#include <iostream>
using namespace std;
int main() {
int size = 5;
int* array = new int[size];
for (int i = 0; i < size; ++i) {
array[i] = i * 2;
}
delete[] array; // 释放数组内存
return 0;
}
动态内存管理的最佳实践
1. 使用智能指针
智能指针(如 std::unique_ptr
、std::shared_ptr
和 std::weak_ptr
)可以帮助自动管理动态分配的内存,避免内存泄漏和双删等问题。
示例:使用 std::unique_ptr
cpp
深色版本
#include <iostream>
#include <memory>
using namespace std;
int main() {
unique_ptr<int> ptr(new int); // 使用智能指针
*ptr = 10;
// 智能指针会在离开作用域时自动释放内存
return 0;
}
2. RAII(Resource Acquisition Is Initialization)
RAII 是一种编程技术,它通过在对象的生命周期内自动管理资源(如内存、文件句柄等),来确保资源的正确释放。
示例:使用 RAII 管理文件
cpp
深色版本
#include <iostream>
#include <fstream>
using namespace std;
class SafeFile {
private:
ofstream file;
public:
SafeFile(const string& filename)
: file(filename, ios::out | ios::binary) {
if (!file.is_open()) {
throw runtime_error("Failed to open file.");
}
}
~SafeFile() {
file.close();
}
void write(const string& data) {
if (!file) {
throw runtime_error("Failed to write to file.");
}
file << data;
}
};
int main() {
try {
SafeFile file("data.txt");
file.write("Some data to be written.");
}
catch (const runtime_error& e) {
cerr << "Caught exception: " << e.what() << endl;
}
return 0;
}
3. 避免内存泄漏
确保所有通过 new
分配的内存都通过 delete
释放,或者使用智能指针自动管理内存。
示例:避免内存泄漏
cpp
深色版本
#include <iostream>
using namespace std;
int main() {
int* ptr = new int;
*ptr = 10;
delete ptr; // 不释放会导致内存泄漏
return 0;
}
4. 避免双删
确保同一个指针只释放一次,避免重复释放内存。
示例:避免双删
cpp
深色版本
#include <iostream>
using namespace std;
int main() {
int* ptr = new int;
*ptr = 10;
delete ptr; // 正确释放内存
// delete ptr; // 错误:双删
return 0;
}
动态内存分配的高级用法
1. 动态分配对象数组
cpp
深色版本
#include <iostream>
using namespace std;
class MyClass {
public:
MyClass(int value) : m_value(value) {}
void print() const { cout << "Value: " << m_value << endl; }
private:
int m_value;
};
int main() {
int size = 5;
MyClass* objects = new MyClass[size];
for (int i = 0; i < size; ++i) {
objects[i] = MyClass(i * 2);
objects[i].print();
}
delete[] objects; // 释放数组内存
return 0;
}
2. 动态分配字符串
cpp
深色版本
#include <iostream>
#include <cstring>
using namespace std;
int main() {
const char* str = "Hello, World!";
char* copy = new char[strlen(str) + 1];
strcpy(copy, str);
cout << "Copied String: " << copy << endl;
delete[] copy; // 释放内存
return 0;
}
总结
动态内存管理是 C++ 编程中不可或缺的一部分,它允许你在运行时根据需要分配和释放内存。通过使用 new
和 delete
操作符,可以灵活地管理动态内存。然而,手动管理内存容易引入内存泄漏、双删等问题。为了避免这些问题,现代 C++ 推荐使用智能指针(如 std::unique_ptr
和 std::shared_ptr
)来自动管理内存。同时,采用 RAII 技术也可以帮助你更安全地管理资源。理解并正确应用这些技术和最佳实践,可以帮助你编写出更健壮、更高效的程序。