【问题标题】:C++ class constructor is called twice when new operator is overriden - why重写 new 运算符时,C++ 类构造函数被调用两次 - 为什么
【发布时间】:2018-11-28 18:20:01
【问题描述】:

我写了以下代码来理解运算符new

#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;
}

当我运行它时,输出如下

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

叫新狗

在 Dog 类中重写的运算符新称为 size_t n = 8 Sizeof(Dog) = 8

全局运算符新调用 - 请求:8,在:0xf15c20

狗构造

狗构造

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

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

谢谢

【问题讨论】:

    标签: c++


    【解决方案1】:

    这是因为您在为正在构造的 Dog object 分配存储时,使用重载 operator new 内部的placement new 构造了一个 Dog 对象:

    ::new (storage) Dog();
    

    运算符 new 不应该构造一个对象,它应该只分配内存,编译器会发出代码来使用分配的内存构造一个对象。

    【讨论】:

    • 您的意思是展示位置分配正在调用 ::new (storage) Dog();在 Dog 类的重载 new 运算符中。那么是否可以将 new 运算符覆盖为 void* operator new(size_t n) {void* storage = ::operator new (n);返回存储;}
    • @3mr ::new (storage) Dog(); 是一个新的放置,它不分配任何东西,只使用提供的存储构造对象。它不应该在重载的operator new内部使用
    • 在我尝试过的主要方法中 void* pDog = operator new (sizeof(Dog));新的(pDog)狗();但是第二行给出了编译错误,并且当我将它作为 ::new(pDog) Dog(); 时工作。 this :: 出现在新关键字之前是什么意思。请帮忙
    • @3mr :: 是名称解析运算符。当它用作限定名称的前导部分时,此名称指的是全局名称空间中的名称。那就是::new (storage) Dog(); 调用了一个全局放置操作符 new(它没有被重载)。
    【解决方案2】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-01-31
      • 2014-06-16
      • 1970-01-01
      • 2018-05-09
      • 1970-01-01
      • 2013-12-11
      • 1970-01-01
      相关资源
      最近更新 更多