C++ 内存分配详解

内存分配是C++编程中的核心概念,主要分为栈分配堆分配两种方式。

1. 栈内存分配(自动分配)

栈内存由编译器自动管理,分配和释放速度快。
特点:

  • 自动分配和释放
  • 大小有限(通常几MB)
  • 局部变量存储在栈上
  • 函数结束时自动释放
cpp 复制代码
#include <iostream>
using namespace std;

void stackExample() {
    int x = 10;              // 栈上分配
    int arr[100];            // 栈上分配数组(大小固定)
    double d = 3.14;
    
    // 函数结束时,所有局部变量自动释放
}

int main() {
    stackExample();
    return 0;
}

2. 堆内存分配(动态分配)

堆内存由程序员手动管理,使用 newdelete 操作符。
特点:

  • 手动分配和释放
  • 内存较大(受系统限制)
  • 生命周期由程序员控制
  • 分配速度较慢

3. new 和 delete 的基本用法

分配单个变量

cpp 复制代码
// 分配内存
int *p = new int;     // 分配一个int类型的内存
*p = 42;              // 向分配的内存写入值

// 分配并初始化
int *p2 = new int(100);  // 直接初始化为100

// 释放内存
delete p;
delete p2;
p = nullptr;  // 好习惯:释放后置为空指针
p2 = nullptr;

分配数组

cpp 复制代码
// 分配数组
int size = 10;
int *arr = new int[size];  // 分配10个int的数组

// 初始化数组
for (int i = 0; i < size; i++) {
    arr[i] = i * 10;
}

// 释放数组内存(必须使用 delete[])
delete[] arr;
arr = nullptr;

4. new 的高级用法

初始化数组(C++11及以上)

cpp 复制代码
// 使用初始化列表
int *arr1 = new int[5]{1, 2, 3, 4, 5};

// 默认初始化(所有元素为0)
int *arr2 = new int[5]();  // 所有元素初始化为0

// 分配并初始化字符串
char *str = new char[10]{'H', 'e', 'l', 'l', 'o', '\0'};

分配多维数组

cpp 复制代码
// 方法1:使用一维数组模拟
int rows = 3, cols = 4;
int *matrix = new int[rows * cols];
// 访问元素:matrix[i * cols + j]

// 方法2:指针数组(更直观但需要多层释放)
int **matrix2 = new int*[rows];
for (int i = 0; i < rows; i++) {
    matrix2[i] = new int[cols];
}

// 使用
for (int i = 0; i < rows; i++) {
    for (int j = 0; j < cols; j++) {
        matrix2[i][j] = i * j;
    }
}

// 释放多维数组
for (int i = 0; i < rows; i++) {
    delete[] matrix2[i];
}
delete[] matrix2;
matrix2 = nullptr;

5. 内存分配失败处理

传统方式(抛出异常)

cpp 复制代码
try {
    int *p = new int[1000000000000];  // 分配过大的内存
    delete[] p;
} catch (const std::bad_alloc& e) {
    cout << "内存分配失败: " << e.what() << endl;
}

使用 std::nothrow(不抛出异常)

cpp 复制代码
int *p = new(std::nothrow) int[1000000000000];
if (p == nullptr) {
    cout << "内存分配失败" << endl;
    // 处理错误
} else {
    delete[] p;
}

6. 动态分配对象

单个对象

cpp 复制代码
class MyClass {
public:
    int value;
    MyClass(int v) : value(v) {
        cout << "构造函数: " << value << endl;
    }
    ~MyClass() {
        cout << "析构函数: " << value << endl;
    }
};

int main() {
    // 动态创建对象
    MyClass *obj = new MyClass(42);
    
    // 使用对象
    cout << "对象值: " << obj->value << endl;
    
    // 手动释放
    delete obj;
    obj = nullptr;
    
    return 0;
}

7. 内存分配的最佳实践

1. 总是检查分配是否成功

cpp 复制代码
int *p = new(std::nothrow) int[1000];
if (!p) {
    // 处理内存不足的情况
    cerr << "内存不足!" << endl;
    return -1;
}

2. 配对使用 new/deletenew[]/delete[]

cpp 复制代码
// 正确
int *single = new int;
delete single;

int *array = new int[10];
delete[] array;  // 注意是 delete[]

// 错误
int *arr = new int[10];
delete arr;      // 错误!应该使用 delete[]

3. 避免内存泄漏

cpp 复制代码
void badFunction() {
    int *p = new int[100];
    // 忘记 delete[] p;  // 内存泄漏!
}

void goodFunction() {
    int *p = new int[100];
    // 使用内存...
    delete[] p;  // 正确释放
    p = nullptr;
}

4. 使用 RAII(Resource Acquisition Is Initialization)

cpp 复制代码
class SmartArray {
private:
    int *data;
    int size;
public:
    SmartArray(int n) : size(n) {
        data = new int[n];
    }
    
    ~SmartArray() {
        delete[] data;
        data = nullptr;
    }
    
    // 禁用拷贝构造和赋值(或实现深拷贝)
    SmartArray(const SmartArray&) = delete;
    SmartArray& operator=(const SmartArray&) = delete;
    
    // 移动语义
    SmartArray(SmartArray&& other) noexcept
        : data(other.data), size(other.size) {
        other.data = nullptr;
        other.size = 0;
    }
};

int main() {
    SmartArray arr(100);  // 自动管理内存
    // 函数结束时自动调用析构函数释放内存
    return 0;
}
相关推荐
JH30732 小时前
Java 是值传递:深入理解参数传递机制
java·开发语言·windows
alibli2 小时前
一文学会设计模式之创建型模式及最佳实现
c++·设计模式
️停云️2 小时前
C++类型转换、IO流与特殊类的设计
c语言·开发语言·c++
while(1){yan}2 小时前
文件IO的常识
java·开发语言·青少年编程·电脑常识
进击的荆棘2 小时前
C++起始之路——类和对象(下)
开发语言·c++
帅得不敢出门3 小时前
精简Android SDK(AOSP)的git项目提高git指令速度
android·java·开发语言·git·elasticsearch
liu****3 小时前
10.排序
c语言·开发语言·数据结构·c++·算法·排序算法
爱写Bug的小孙3 小时前
Tools、MCP 和 Function Calling
开发语言·人工智能·python·ai·ai编程·工具调用
小小Fred3 小时前
FreeRTOS函数prvInitialiseNewTask解析
java·开发语言