2015-10-31 39 views
0

有人知道为什么调用Dogter operator的Latter语法在分配后调用默认构造函数,最终调用2构造函数?类成员操作符new,调用构造函数两次

我想知道如果我做错事,我该怎么办:

Dog *ptr = new("arg") Dog();

,而无需调用构造函数2。并且不使用任何技巧,比如检查默认构造函数,如果对象已经构造。下面是代码:

class Dog 
{ 
public: 

    Dog() // default 
    { 
     std::cout << "default Dog constructor [" << this << "]" << std::endl; 
    } 

    Dog(int x) // int argument 
    { 
     std::cout << "dog constructor int " << x << "[" << this << "]" << std::endl; 
    } 

    Dog(const std::string& word) // std::string argument 
    { 
     std::cout << "dog constructor std::string: " << word << " ["<< this << "]" << std::endl; 
    } 

    Dog(std::string &&word) // rvalue string argument 
    { 
     std::cout << "dog constructor std::string&& rvalue: " << word << " [" << this << "]" << std::endl; 
    } 



    // custom operator new 
    static void *operator new(std::size_t size) noexcept // for default constructor 
    { 
     Dog *ptr = (Dog*)malloc(size); // allocate memory 
     if (ptr) // if allocate ok 
     { 
      ::new(ptr) Dog(); // call default constructor on object in memory 
      return ptr; // returns 
     } 
     else 
      return nullptr; 

    } 

    template<class T> 
    static void * operator new(std::size_t size, T&& value) noexcept // for argument constructor 
    { 
     Dog *ptr = (Dog*) malloc(size); // allocate the memory 
     if (ptr) 
     { 
      ::new (ptr) Dog(std::forward<T>(value)); // pass the argument exactly as was passed to operator new, 
                 // using perfect forwarding 
      return ptr; 
     } 
     else 
      return nullptr; 

    } 


    ~Dog() { std::cout << "destructor " << std::endl; } 
}; 



int main(void) 
{ 




    Dog *d = (Dog*) Dog::operator new(sizeof(Dog), "Const Char * Argument"); // argument version 
    Dog *d2 = (Dog*)Dog::operator new(sizeof(Dog)); // default constructor argument 

    //1 this works as expected, do what you specified in the member operator new, everything goes normal. 




    Dog *d3 = new Dog(); // default constructor 
    Dog *d4 = new("Const Char * Argument") Dog(); // argument constructor 

    // this is shorter, goes into your member operator new, BUT when it returns to this scope, 
    // call the default constructor for *d3, and for *d4 too. 

    // so this ends up calling constructors twice for both objects. 



} 

所以,我是混合结构的分配,没有理由这样做,在这里,也许有在操作一些使用了新的[]构建阵列用除默认构造函数以外的构造函数。

但最好的方式来定义这些成员运营商:

class Dog { 
public: 
// ....... 

     // custom operator new 
    static void *operator new(std::size_t size) noexcept // for default constructor 
    { 
     void *memory = malloc(size); // allocate memory 
     if (memory) // if allocate ok 
     { 
      return memory; // returns 
     } 
     else 
      return nullptr; 

    } 

    static void *operator new[](std::size_t size) noexcept 
    { 
     void *memory = malloc(size); // allocate memory 
     if (memory) // if allocate ok 
     { 
      return memory; // returns 
     } 
     else 
      return nullptr; 
    } 

    static void operator delete(void *block) noexcept 
    { 
     free(block); 
    } 

    static void operator delete[](void *block) noexcept 
    { 
     free(block); 
    } 

    ~Dog() { std::cout << "destructor " << std::endl; } 
}; 



int main(void) 
{ 
    // now we can use new operator normaly without complications 
    Dog *d1 = new Dog[10]; // default constructor on all objects 

    Dog *d2 = new Dog("const char * argument"); // call std::string&& constructor 

    delete[] d1; 
    delete d2; 





} 
+3

你为什么在C++代码中使用'malloc'? –

回答

3

使用(关键字)新:它调用分配operator new和调用构造函数(!)。

注意:当提供一个新的操作员时,你也应该提供一个操作员删除(在你的情况下它会免费)。另外,不要忘记阵列版本。

+0

恢复,要正确使用“Dog”的新成员运算符,我必须使用第一种语法。 Dog * ptr =(Dog *)Dog :: operator new(sizeof(Dog),arg); –

+0

@RafaelMoura不要混合分配和建设。 –

+1

哦,我知道了,它不应该从成员操作符new调用构造函数,而是使用默认方式调用它,并且可以正常工作。谢谢。 –