In C++, why is `new` needed to dynamically create an object rather just allocation?

前端 未结 5 768
猫巷女王i
猫巷女王i 2021-01-18 08:30

I\'ve got this trivial class hierarchy:

class Base {
public:
    virtual int x( ) const = 0;
};

class Derived : public Base {
    int _x;
public:
    Derive         


        
5条回答
  •  醉梦人生
    2021-01-18 09:03

    Classes with virtual members contain a pointer to a so-called vtable - basically a table of function pointers to the implementation of these virtual members. When you use operator new, the constructor is called, which, even if it is an implicit constructor, will set up this pointer to the vtable properly.

    However, malloc does not call the constructor. The vtable pointer is left uninitialized, point to some random memory. When you then attempt to call a virtual function, you dereference a bad pointer and crash (undefined behavior).

    The solution is to use placement new to initialize the object before using it:

    int main( ) {
        Derived *d;
        d = (Derived*) malloc( sizeof(Derived) );
        new(d) Derived(123); // invoke constructor
    // You could also do:
    //    new(d) Derived;
    //    *d = Derived( 123 );
    
        std::cout << d->x() << std::endl; // crash
    
        // Although in your case it does not matter, it's good to clean up after yourself by
        // calling the destructor
        d->~Derived();
        return 0;
    }
    

    Some important things to note:

    • Alignment is not a problem. Memory from malloc is properly aligned for any C++ type.
    • Assigning with = does not help. The default implementation of = copies all member variables, but the vtable pointer is not a member and is not copied.
    • Construction is not required for POD types. Non-POD types may or may not require it (it's undefined behavior if you don't). In particular, the constructor also calls member variable constructors; so if you don't construct the outer object, inner objects may be broken as well.

提交回复
热议问题