C++ 编程中,虽然 new 运算符可以动态分配内存,但在现代 C++ 编程实践中,应尽量避免手动使用 new 和 delete,可以使用栈对象(自动释放)、std::unique_ptr 或 std::shared_ptr、std::make_unique / std::make_shared。

1、容易造成内存泄漏

使用 new 分配内存后,如果忘记使用 delete 释放,就会导致内存泄漏。程序复杂后难以保证每个 new 都能对应一个 delete

#include<iostream>
using namespace std;

void memoryLeakExample() {
     // 动态分配内存,并初始化为 10
    int* ptr = new int(10);  

    std::cout << "值: " << *ptr << std::endl;

    // 忘记 delete ptr; 这里会导致内存泄漏
    // 正确写法应为:delete ptr;
}

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

2、异常安全性差

如果在 new 后发生异常,中间变量可能没有释放,从而造成资源泄露。

#include <iostream>
#include <stdexcept>

void func() {
    int* ptr = new int(42);
    throw std::runtime_error("error");  // 内存泄漏:ptr 没有 delete
}

int main() {
    try {
        func();
    } catch (const std::runtime_error& e) {
        std::cerr << "Caught exception: " << e.what() << std::endl;
    }
    return 0;
}

3、难以管理生命周期

手动管理内存生命周期不易维护和调试。特别在多线程或复杂逻辑中,容易出现野指针、悬垂指针。

#include <iostream>

class Data {
public:
    Data(int v) : value(v) {
        std::cout << "Data created\n";
    }
    ~Data() {
        std::cout << "Data destroyed\n";
    }
    void show() const {
        std::cout << "Value: " << value << std::endl;
    }
private:
    int value;
};

void process(Data* d) {
    d->show();  // 使用外部传入的指针
}

int main() {
    Data* ptr = new Data(10);
    delete ptr;        // 显式释放
    process(ptr);      // ❌ 悬挂指针!访问已释放内存
    return 0;
}

4、现代 C++ 提供更安全的替代品

使用智能指针(如 std::unique_ptr, std::shared_ptr)更安全,自动释放内存。使用容器(如 std::vector, std::string)可以避免裸指针操作。

#include <iostream>
#include <memory>  // 包含 std::make_unique 和 std::unique_ptr

int main() {
    // 创建一个指向 int 的 unique_ptr,初始化为 42
    auto ptr = std::make_unique<int>(42);

    // 访问并打印指针指向的值
    std::cout << "Value: " << *ptr << std::endl;

    // 不需要手动 delete,ptr 离开作用域时会自动释放内存
    return 0;
}

5、可能影响程序性能

new/delete 比栈内存或智能指针操作开销更大。尤其是在频繁分配/释放内存时,可能影响性能和缓存局部性。

推荐文档