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;
}
相关推荐
2501_921649495 小时前
企业定制金融数据 API:从架构设计到 Python 接入实战
大数据·开发语言·python·websocket·金融·量化
直奔標竿6 小时前
SpringAI + RAG + MCP + Agent 零基础全栈实战(完结篇)| 27课完整汇总,Java开发者AI转型必看
java·开发语言·人工智能·spring boot·后端·spring
reasonsummer6 小时前
【教学类-160-13】20260422 AI视频培训-练习013“豆包AI视频《师幼互动》+豆包图片风格:CG动画”
开发语言·python
曹牧6 小时前
Java:处理 HTTP 请求的 Content-Type
java·开发语言
itzixiao6 小时前
L1-066 猫是液体(5分)[java][python]
java·开发语言·python·算法
Lightning-py6 小时前
Python 配置日志(Logging)
开发语言·python
隔窗听雨眠7 小时前
MySQL主从延迟根因诊断法
开发语言·php
Hui_AI7207 小时前
基于RAG的农产品GEO溯源智能问答系统实现
开发语言·网络·人工智能·python·算法·创业创新
CDwenhuohuo7 小时前
前端文件预览
开发语言·前端·javascript
charlie1145141917 小时前
通用GUI编程技术——图形渲染实战(三十八)——顶点缓冲与输入布局:GPU的第一个三角形
开发语言·c++·学习·图形渲染·win32