C++ new关键字运算符重载

#include <iostream>
#include <vector>
#include <list>

class MyClass {
public:
    // 构造函数  
    MyClass(int value) : data(value) {
        std::cout << "MyClass constructor called with value " << data << std::endl;
    }

    // 析构函数  
    ~MyClass() {
        std::cout << "MyClass destructor called" << std::endl;
    }

    // 静态成员函数,用于重载new  
    void* operator new(size_t size) {
        void* p = malloc(size);
        std::cout << "Custom new called for MyClass, allocating " << size << " bytes at " << p << std::endl;
        return p;
    }

    // 静态成员函数,用于重载delete  
    void operator delete(void* p) noexcept {
        std::cout << "Custom delete called for MyClass, freeing memory at " << p << std::endl;
        free(p);
    }

    int data;
    std::list<int> arr;
};

int main() {
    MyClass* ptr = new MyClass(42);

    ptr->arr.push_back(1);

    delete ptr;


    return 0;
}

在C++中,当你使用new运算符(无论是重载版本还是默认版本)来创建类的对象时,对象的构造函数会在分配内存之后、但在将内存地址返回给调用者之前被调用。这确保了对象在使用之前被正确地初始化。

上述例子发生的事情的顺序如下

MyClass::operator new(size_t size)被调用以在堆上分配足够的内存来存储MyClass对象。
分配的内存地址(由malloc或其他内存分配函数返回)被传递给构造函数MyClass(int value)。
MyClass(int value)构造函数在分配的内存上被调用,并使用提供的参数42来初始化对象。
构造函数完成后,new表达式返回指向新创建并初始化的对象的指针。
因此,构造函数是在内存分配之后但在将指针返回给调用者之前被调用的。这是确保对象在使用之前处于有效状态的重要步骤。

需要注意的是,如果你重载了new运算符但没有正确地处理内存分配失败的情况(例如,没有检查malloc的返回值是否为nullptr),并且内存分配失败,那么构造函数将不会被调用,因为根本没有分配内存来存储对象。

在这种情况下,你应该让重载的new运算符抛出异常(如std::bad_alloc),以便调用者可以适当地处理内存分配失败的情况。

posted on 2024-06-28 09:28  寒魔影  阅读(23)  评论(0编辑  收藏  举报

导航