动态内存分配是 C++ 中的重要概念,它允许程序在运行时根据需要分配和释放内存。这与静态内存分配(编译时确定大小)形成对比。
内存分区概述
程序内存布局
#include <iostream>
// 全局变量 - 存储在数据段
int global_var = 100;
static int static_global = 200;
// 常量 - 存储在只读数据段
const int const_global = 300;
void demonstrateMemoryLayout() {
// 局部变量 - 存储在栈上
int local_var = 400;
static int static_local = 500; // 存储在数据段
// 动态分配 - 存储在堆上
int* heap_var = new int(600);
std::cout << "内存布局演示:" << std::endl;
std::cout << "全局变量地址: " << &global_var << std::endl;
std::cout << "静态全局变量地址: " << &static_global << std::endl;
std::cout << "常量地址: " << &const_global << std::endl;
std::cout << "局部变量地址: " << &local_var << std::endl;
std::cout << "静态局部变量地址: " << &static_local << std::endl;
std::cout << "堆变量地址: " << heap_var << std::endl;
std::cout << "函数地址: " << reinterpret_cast<void*>(demonstrateMemoryLayout) << std::endl;
delete heap_var;
}
int main() {
demonstrateMemoryLayout();
return 0;
}
new 和 delete 操作符
基本的 new 和 delete
#include <iostream>
int main() {
// 1. 分配单个变量
int* ptr1 = new int; // 未初始化
int* ptr2 = new int(42); // 初始化为 42
int* ptr3 = new int{100}; // C++11 统一初始化
std::cout << "动态分配的单个变量:" << std::endl;
std::cout << "*ptr1 = " << *ptr1 << " (未初始化,可能是垃圾值)" << std::endl;
std::cout << "*ptr2 = " << *ptr2 << std::endl;
std::cout << "*ptr3 = " << *ptr3 << std::endl;
// 释放内存
delete ptr1;
delete ptr2;
delete ptr3;
// 2. 分配数组
int size = 5;
int* arr1 = new int[size]; // 未初始化数组
int* arr2 = new int[size](); // 零初始化数组
int* arr3 = new int[size]{1,2,3,4,5}; // C++11 列表初始化
std::cout << "\n动态分配的数组:" << std::endl;
// 初始化第一个数组
for (int i = 0; i < size; ++i) {
arr1[i] = i * 10;
}
std::cout << "arr1: ";
for (int i = 0; i < size; ++i) {
std::cout << arr1[i] << " ";
}
std::cout << std::endl;
std::cout << "arr2 (零初始化): ";
for (int i = 0; i < size; ++i) {
std::cout << arr2[i] << " ";
}
std::cout << std::endl;
std::cout << "arr3 (列表初始化): ";
for (int i = 0; i < size; ++i) {
std::cout << arr3[i] << " ";
}
std::cout << std::endl;
// 释放数组内存
delete[] arr1;
delete[] arr2;
delete[] arr3;
return 0;
}
new 和 delete 的匹配规则
#include <iostream>
class TestClass {
public:
int value;
TestClass(int v = 0) : value(v) {
std::cout << "构造函数调用: " << value << std::endl;
}
~TestClass() {
std::cout << "析构函数调用: " << value << std::endl;
}
};
int main() {
std::cout << "=== 单个对象 ===" << std::endl;
TestClass* obj = new TestClass(42);
delete obj; // 正确:new 对应 delete
std::cout << "\n=== 对象数组 ===" << std::endl;
TestClass* arr = new TestClass[3]{TestClass(1), TestClass(2), TestClass(3)};
delete[] arr; // 正确:new[] 对应 delete[]
std::cout << "\n=== 错误示例(注释掉避免未定义行为) ===" << std::endl;
// TestClass* wrong1 = new TestClass(100);
// delete[] wrong1; // 错误!new 对应 delete[]
// TestClass* wrong2 = new TestClass[2];
// delete wrong2; // 错误!new[] 对应 delete
// 内存泄漏示例
std::cout << "\n=== 内存泄漏示例 ===" << std::endl;
for (int i = 0; i < 3; ++i) {
int* leak = new int(i); // 分配内存但从不释放
std::cout << "分配了内存,值为: " << *leak << std::endl;
// 缺少 delete leak; - 这会导致内存泄漏
}
return 0;
}
动态数组
一维动态数组
#include <iostream>
#include <algorithm>
class DynamicIntArray {
private:
int* data;
size_t size;
size_t capacity;
public:
// 构造函数
DynamicIntArray(size_t initial_capacity = 4)
: size(0), capacity(initial_capacity) {
data = new int[capacity];
std::cout << "创建动态数组,容量: " << capacity << std::endl;
}
// 析构函数
~DynamicIntArray() {
delete[] data;
std::cout << "销毁动态数组" << std::endl;
}
// 拷贝构造函数
DynamicIntArray(const DynamicIntArray& other)
: size(other.size), capacity(other.capacity) {
data = new int[capacity];
std::copy(other.data, other.data + size, data);
std::cout << "拷贝构造动态数组" << std::endl;
}
// 赋值操作符
DynamicIntArray& operator=(const DynamicIntArray& other) {
if (this != &other) {
delete[] data;
size = other.size;
capacity = other.capacity;
data = new int[capacity];
std::copy(other.data, other.data + size, data);
std::cout << "赋值操作动态数组" << std::endl;
}
return *this;
}
// 添加元素
void push_back(int value) {
if (size >= capacity) {
resize();
}
data[size++] = value;
}
// 访问元素
int& operator[](size_t index) {
return data[index];
}
const int& operator[](size_t index) const {
return data[index];
}
// 获取大小
size_t getSize() const { return size; }
size_t getCapacity() const { return capacity; }
// 打印数组
void print() const {
std::cout << "数组 [大小:" << size << ", 容量:" << capacity << "]: ";
for (size_t i = 0; i < size; ++i) {
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
private:
void resize() {
size_t new_capacity = capacity * 2;
int* new_data = new int[new_capacity];
// 复制旧数据
std::copy(data, data + size, new_data);
delete[] data;
data = new_data;
capacity = new_capacity;
std::cout << "数组扩容到: " << capacity << std::endl;
}
};
int main() {
DynamicIntArray arr;
// 添加元素,观察扩容过程
for (int i = 1; i <= 10; ++i) {
arr.push_back(i * 10);
arr.print();
}
// 测试拷贝构造
std::cout << "\n测试拷贝构造:" << std::endl;
DynamicIntArray arr2 = arr;
arr2.print();
// 测试赋值操作
std::cout << "\n测试赋值操作:" << std::endl;
DynamicIntArray arr3;
arr3 = arr;
arr3.print();
return 0;
}
二维动态数组
#include <iostream>
class Dynamic2DArray {
private:
int** data;
size_t rows;
size_t cols;
public:
// 构造函数
Dynamic2DArray(size_t r, size_t c) : rows(r), cols(c) {
// 分配行指针数组
data = new int*[rows];
// 为每一行分配内存
for (size_t i = 0; i < rows; ++i) {
data[i] = new int[cols];
}
std::cout << "创建 " << rows << "x" << cols << " 的二维数组" << std::endl;
}
// 析构函数
~Dynamic2DArray() {
// 先释放每一行
for (size_t i = 0; i < rows; ++i) {
delete[] data[i];
}
// 再释放行指针数组
delete[] data;
std::cout << "销毁二维数组" << std::endl;
}
// 访问元素
int*& operator[](size_t row) {
return data[row];
}
const int* operator[](size_t row) const {
return data[row];
}
// 获取维度
size_t getRows() const { return rows; }
size_t getCols() const { return cols; }
// 初始化数组
void initialize(int start_value = 0) {
int value = start_value;
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
data[i][j] = value++;
}
}
}
// 打印数组
void print() const {
std::cout << "二维数组内容:" << std::endl;
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
std::cout << data[i][j] << "\t";
}
std::cout << std::endl;
}
}
};
// 另一种实现:使用连续内存块
class Continuous2DArray {
private:
int* data;
size_t rows;
size_t cols;
public:
Continuous2DArray(size_t r, size_t c) : rows(r), cols(c) {
data = new int[rows * cols];
std::cout << "创建连续内存的 " << rows << "x" << cols << " 数组" << std::endl;
}
~Continuous2DArray() {
delete[] data;
std::cout << "销毁连续内存数组" << std::endl;
}
// 访问元素
int& operator()(size_t row, size_t col) {
return data[row * cols + col];
}
const int& operator()(size_t row, size_t col) const {
return data[row * cols + col];
}
void initialize(int start_value = 0) {
for (size_t i = 0; i < rows * cols; ++i) {
data[i] = start_value + i;
}
}
void print() const {
std::cout << "连续内存数组内容:" << std::endl;
for (size_t i = 0; i < rows; ++i) {
for (size_t j = 0; j < cols; ++j) {
std::cout << data[i * cols + j] << "\t";
}
std::cout << std::endl;
}
}
size_t getRows() const { return rows; }
size_t getCols() const { return cols; }
};
int main() {
std::cout << "=== 指针数组方式的二维数组 ===" << std::endl;
Dynamic2DArray matrix1(3, 4);
matrix1.initialize(1);
matrix1.print();
// 修改元素
matrix1[1][2] = 999;
std::cout << "\n修改 [1][2] 为 999 后:" << std::endl;
matrix1.print();
std::cout << "\n=== 连续内存方式的二维数组 ===" << std::endl;
Continuous2DArray matrix2(3, 4);
matrix2.initialize(100);
matrix2.print();
// 修改元素
matrix2(2, 1) = 888;
std::cout << "\n修改 (2,1) 为 888 后:" << std::endl;
matrix2.print();
return 0;
}
内存管理的常见问题
内存泄漏
#include <iostream>
#include <vector>
// 内存泄漏示例
void memoryLeakExamples() {
std::cout << "=== 内存泄漏示例 ===" << std::endl;
// 1. 简单内存泄漏
{
int* ptr = new int(42);
// 忘记 delete ptr; - 内存泄漏!
}
// 2. 异常导致的内存泄漏
try {