MST

星途 面试题库

面试题:C++中new和delete的基本使用及内存泄漏场景

请描述C++中new和delete操作符的基本用法。并举例说明在使用new和delete进行内存管理时,可能会导致内存泄漏的场景有哪些,以及如何避免这些内存泄漏。
31.5万 热度难度
编程语言C++

知识考点

AI 面试

面试题答案

一键面试

new操作符基本用法

  1. 分配单个对象
    • 语法:type* pointer = new type;
    • 例如:int* num = new int; 这行代码在堆上分配了一个 int 类型的空间,并返回指向该空间的指针,赋值给 num
    • 也可以在分配时初始化:int* num = new int(5); 这里初始化 int5
  2. 分配数组
    • 语法:type* pointer = new type[size];
    • 例如:int* arr = new int[10]; 在堆上分配了一个包含 10int 类型元素的数组,并返回指向数组首元素的指针,赋值给 arr

delete操作符基本用法

  1. 释放单个对象
    • 语法:delete pointer;
    • 例如:int* num = new int; delete num; 释放之前用 new 分配的 int 类型对象。
  2. 释放数组
    • 语法:delete[] pointer;
    • 例如:int* arr = new int[10]; delete[] arr; 释放之前用 new 分配的数组。

可能导致内存泄漏的场景

  1. 忘记调用delete
    • 例如:
void leak1() {
    int* num = new int;
    // 没有调用delete num;
}
  • 在函数 leak1 中,分配了一个 int 类型的对象,但没有释放,函数结束时,这块内存无法再被访问,导致内存泄漏。
  1. 异常处理不当
void leak2() {
    int* arr = new int[10];
    try {
        // 可能抛出异常的代码
        throw std::exception();
    } catch(...) {
        // 没有释放arr
    }
}
  • leak2 函数中,分配了数组 arr,如果在 try 块中抛出异常,并且 catch 块没有释放 arr,就会导致内存泄漏。
  1. 指针赋值丢失
void leak3() {
    int* num1 = new int;
    int* num2 = num1;
    num1 = nullptr;
    // 此时num1指向nullptr,而num2也没有delete,导致内存泄漏
}
  • 这里最初 num1 指向新分配的内存,num2 也指向相同内存,然后 num1 被赋值为 nullptr,而 num2 没有释放内存,造成内存泄漏。

避免内存泄漏的方法

  1. 智能指针
    • std::unique_ptr
#include <memory>
void noLeak1() {
    std::unique_ptr<int> num(new int);
    // 函数结束时,std::unique_ptr自动调用delete释放内存
}
  • std::shared_ptr
#include <memory>
void noLeak2() {
    std::shared_ptr<int> num(new int);
    // 当引用计数为0时,自动释放内存
    std::shared_ptr<int> num2 = num;
}
  1. RAII(Resource Acquisition Is Initialization)
    • 自定义类来管理资源,在构造函数中分配资源,在析构函数中释放资源。
class Resource {
public:
    Resource() : data(new int) {}
    ~Resource() { delete data; }
private:
    int* data;
};
void noLeak3() {
    Resource res;
    // 函数结束时,res的析构函数会释放分配的内存
}
  1. 异常安全处理
    • 使用智能指针或RAII类在异常发生时能自动释放资源。如果手动管理内存,在 catch 块中正确释放资源。
void noLeak4() {
    int* arr = nullptr;
    try {
        arr = new int[10];
        // 可能抛出异常的代码
        throw std::exception();
    } catch(...) {
        if(arr) {
            delete[] arr;
        }
        throw;
    }
}