2012-12-29 13 views
16

Betrachten this code:Verwendet std :: make_shared() benutzerdefinierte Zuordner?

#include <memory> 
#include <iostream> 


class SomeClass { 
public: 
    SomeClass() { 
     std::cout << "SomeClass()" << std::endl; 
    } 

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

    void* operator new(std::size_t size) { 
     std::cout << "Custom new" << std::endl; 
     return ::operator new(size); 
    } 

    void operator delete(void* ptr, std::size_t size) { 
     std::cout << "Custom delete" << std::endl; 
     ::operator delete(ptr); 
    } 
}; 



int main() { 
    std::shared_ptr<SomeClass> ptr1(new SomeClass); 
    std::cout << std::endl << "Another one..." << std::endl << std::endl; 
    std::shared_ptr<SomeClass> ptr2(std::make_shared<SomeClass>()); 
    std::cout << std::endl << "Done!" << std::endl << std::endl; 
} 

Hier ist seine Ausgabe:

Custom new 
SomeClass() 

Another one... 

SomeClass() 

Done! 

~SomeClass() 
~SomeClass() 
Custom delete 

Offensichtlich std::make_shared() die new Betreiber nicht angerufen hat - es ist eine benutzerdefinierte allocator verwenden. Ist dies das Standardverhalten für std::make_shared()?

Antwort

16

Ja, das ist Standardverhalten. Von dem Standard (§20.7.2.2.6 Shared_ptr Schaffung):

Effekte: Reserviert Speicher für ein Objekt vom Typ T und konstruiert ein Objekt in diesem Speicher über die Platzierung neuer Ausdruck ::new (pv) T(std::forward<Args>(args)...).

Dadurch kann make_shared aus Effizienzgründen den Speicher für das Objekt und die Datenstruktur für den gemeinsamen Zeiger selbst (den "Steuerblock") in einer einzigen Zuweisung zuweisen.

Sie könnten std::allocate_shared verwenden, wenn Sie diese Speicherzuweisung steuern möchten.

+4

'std :: allocate_shared (const A &, Args && ...)' ist auch eine Erwähnung wert. Das erste Argument ist der Allokator zum Aufrufen von 'A :: allocate' on. –

2

auf Mat richtige Antwort zu erweitern, wird make_shared typischerweise durch Zuweisen eines Objekts implementiert, die shared_ptr Referenzzähler und einen Puffer von nicht initialisierten Bytes enthält:

template<typename T> 
    struct shared_count_inplace 
    { 
    long m_count; 
    long weak_count; 
    typename std::aligned_storage<sizeof(T)>::type m_storage; 
    // ... 
    }; 

Dies ist die Art, die auf dem Heap zugewiesen werden , nicht Ihr Typ, also wird Ihr Typ new nicht aufgerufen. Dann wird Ihr Typ mit der Platzierung new am Standort (void*)&m_storage erstellt.

Verwandte Themen