覆盖新运算符时,C ++类构造函数被调用两次-为什么

时间:2018-11-28 10:09:57

标签: c++

我编写了以下代码以了解新的运算符

#include <iostream>

using namespace std;




class Dog {

public:
    Dog() {
        cout << "Dog constructed\n";
    }

    //overriding the new operator of the class and explicitely doing what it internally does
    void* operator new(size_t n) {
        cout << "operator new overriden in Dog class called size_t n = " << n << " Sizeof(Dog) = "<< sizeof(Dog) << endl;

        //Allocating the memory  by calling the global operator new 
        void* storage = ::operator new (n);

        // you can now create the Dog object at the allcated memory at the allocated memory

        ::new (storage) Dog(); //---------> Option 1 to construct the Dog object --> This says create the Dog at the address storage by calling the constructor Dog()

        return storage;
    }

    int m_Age = 5;
    int m_Color = 1;
};

void* operator new(std::size_t size)
{
    void* storage = malloc(size);
    std::cout << "Global operator new called - Asked for: " << size
        << ", at: " << storage << std::endl;
    return storage;
}


int main(int argc, char** argv)
{



    cout << "calling new Dog" << endl;
    Dog* ptr = new Dog;
    int x;
    cin >> x;
    return 0;
}

运行此命令时,输出如下所示

================================================ =

叫新狗

在狗类中被称为size_t n = 8 Sizeof(Dog)= 8的操作员新覆盖

新调用的全局运算符-要求:8,位于:0xf15c20

狗狗

狗狗

========================================

任何知道为什么Dog对象Dog的构造函数被调用两次的想法吗?

谢谢

2 个答案:

答案 0 :(得分:8)

这是因为您在重载运算符new内部使用了new放置构造了Dog对象,同时为正在构造的Dog object分配了存储空间:

::new (storage) Dog();

new运算符永远不要构造对象,它应该仅分配内存,编译器将发出代码以使用分配的内存构造对象。

答案 1 :(得分:4)

这是因为您要在一个函数中构造Dog,而该函数只应该为Dog 分配空间。然后,编译器在那个之上构造第二个Dog

观察到返回类型为void*,即指向未知的指针。如果您打算构造一个Dog,则返回值为Dog*