2012-12-29 15 views
16

Considerare this code:std :: make_shared() usa gli allocatori personalizzati?

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

Qui è la sua uscita:

Custom new 
SomeClass() 

Another one... 

SomeClass() 

Done! 

~SomeClass() 
~SomeClass() 
Custom delete 

Chiaramente, std::make_shared() non ha chiamato l'operatore new - sta usando un allocatore personalizzato. È questo il comportamento standard per std::make_shared()?

risposta

16

Sì, questo è un comportamento standard. Dallo standard (§20.7.2.2.6 creazione shared_ptr):

Effetti: Alloca memoria adatto per un oggetto di tipo T e costruisce un oggetto in quella memoria tramite il posizionamento nuova espressione ::new (pv) T(std::forward<Args>(args)...).

Ciò consente a make_shared di allocare lo storage per l'oggetto e la struttura dati per il puntatore condiviso stesso (il "blocco di controllo") in un'unica allocazione, per motivi di efficienza.

È possibile utilizzare std::allocate_shared se si desidera controllare l'allocazione di memoria.

+4

'std :: allocate_shared (const A &, Args && ...)' vale anche una menzione. Il primo argomento è l'allocatore per chiamare 'A :: allocate' on. –

2

Ad ampliare risposta corretta Mat, make_shared è tipicamente implementato assegnando un oggetto che contiene i shared_ptr conteggi di riferimento e un buffer di byte non inizializzati:

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

Questo è il tipo che verrà assegnato in mucchio , non il tuo tipo, quindi il tuo tipo è new non chiamato. Quindi il tuo tipo verrà costruito utilizzando il posizionamento new nella posizione (void*)&m_storage.

Problemi correlati