2015-10-31 43 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調用構造函數,而是使用默認方式調用它,並且可以正常工作。謝謝。 –