newdelete 在 C++ 中被引入,主要是为了解决 mallocfree 在 C 语言中的一些限制和问题,特别是在面向对象编程方面。以下是 new/delete 相比于 malloc/free 的主要改进:

类型安全和自动大小计算

malloc/free 示例:

#include <stdlib.h>

struct MyStruct {
    int data;
    // ... 其他成员 ...
};

int main() {
    // 使用 malloc 分配内存,需要手动计算大小
    MyStruct* p = (MyStruct*)malloc(sizeof(MyStruct));
    p->data = 10;
    free(p);
    return 0;
}

new/delete 示例:

struct MyStruct {
    int data;
    // ... 其他成员 ...
};

int main() {
    // 使用 new 分配内存,自动处理大小和类型
    MyStruct* p = new MyStruct;
    p->data = 10;
    delete p;
    return 0;
}

改进:

  • new 自动计算所需内存的大小,而 malloc 需要程序员手动计算。
  • new 提供类型安全,返回正确类型的指针,避免了强制类型转换的需要。

构造函数和析构函数的调用

C++ 示例:

class MyClass {
public:
    MyClass() { std::cout << "Constructor called\n"; }
    ~MyClass() { std::cout << "Destructor called\n"; }
};

int main() {
    MyClass* obj = new MyClass; // 调用构造函数
    delete obj;                 // 调用析构函数
    return 0;
}

改进:

  • new 在分配内存时调用对象的构造函数,delete 在释放内存时调用析构函数。
  • mallocfree 只处理内存分配和释放,不调用构造函数和析构函数。

异常处理

C++ 示例:

int main() {
    try {
        int* p = new int[10000000000]; // 尝试分配大量内存
    } catch (const std::bad_alloc& e) {
        std::cerr << "Memory allocation failed: " << e.what() << '\n';
    }
    return 0;
}

改进:

  • new 在内存分配失败时抛出异常(如 std::bad_alloc),而 malloc 在失败时返回 NULL
  • 这使得 new 能够更好地集成到 C++ 的异常处理框架中。

配对简便性

改进:

  • newdelete 是为对象配对的,而 mallocfree 需要显式计算大小。
  • new[]delete[] 用于数组,简化了数组内存管理。

new 的重载

是的,C++ 允许重载 new 操作符。这意味着你可以定义自己的 new 操作符来改变对象的分配方式。重载 new 可以用于自定义内存管理,追踪内存分配,或者引入特殊的内存分配策略。

重载 new 需要提供与系统 new 相同的返回类型和参数列表。最常见的形式是重载全局 newdelete

void* operator new(std::size_t size) {
    std::cout << "Custom new for size " << size << std::endl;
    return std::malloc(size);
}

void operator delete(void* memory) {
    std::cout << "Custom delete" << std::endl;
    std::free(memory);
}

类也可以重载其自身的 newdelete,这对于控制特定类的对象分配非常有用。

class MyClass {
public:
    void* operator new(std::size_t size) {
        std::cout << "MyClass new" << std::endl;
        return std::malloc(size);
    }

    void operator delete(void* memory) {
        std::cout << "MyClass delete" << std::endl;
        std::free(memory);
    }
};

关键字和操作符

new 是操作符,malloc 是函数。

关键字(Keywords)和操作符(Operators)在编程语言中是两个不同的概念:

  • 关键字:这些是编程语言预定义的保留字,每个关键字有特定的含义,并在语言的语法中扮演特定的角色。例如,ifwhilereturn 等在 C++ 中都是关键字。关键字不能用作变量名或函数名。

  • 操作符:操作符用于执行操作,如算术运算、逻辑运算、比较等。在 C++ 中,一些操作符可以被重载,这意味着你可以改变它们的行为以适应特定类型的操作。例如,+-*/new 等都是操作符。

有些情况下,某些关键字也可以被视为操作符。例如,newdelete 在 C++ 中既是关键字也是操作符。它们作为关键字,表示特定的动作(分配和释放内存),同时它们的行为可以像操作符那样被重载。

总结

new/delete 提供了更符合 C++ 面向对象特性的内存管理方式。它们处理类型安全、对象生命周期(构造和析构)、异常安全以及简化语法。然而,这些改进也带来了一定的性能开销,这在某些性能敏感的应用中可能是一个考虑因素。在 C++ 中,new/delete 是推荐的方式,因为它们提供了更安全和便利的内存管理机制。