动态内存分配是 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 {