2014-04-17 11 views

Antwort

12

Warum shared_ptr haben allocate_shared während unique_ptr nicht allocate_unique hat?

shared_ptr es braucht, damit es seinen internen gemeinsam genutzten Zustand (der Referenzzähler und deleter) zuordnen kann, wie auch das gemeinsame Objekt, unter Verwendung der Zuordner. unique_ptr verwaltet nur das Objekt; Es ist also nicht notwendig, einen Zuweiser für die unique_ptr selbst bereitzustellen, und weniger Bedarf für eine allocate Funktion.

(Es gibt auch weniger Bedarf für make_unique aus dem gleichen Grund, das ist wahrscheinlich, warum es nicht in C++ 11, sondern wurde auf C++ 14 von der allgemeinen Nachfrage wegen der Konsistenz hinzugefügt. vielleicht wird die gleiche Forderung allocate_unique zu einem zukünftigen Standard hinzufügen.)

muss ich die mir Puffer zuweisen und dann zuweisen zu einem unique_ptr?

Ja. Oder Sie könnten Ihre eigenen allocate_unique schreiben; Im Gegensatz zu allocate_shared ist es möglich und relativ einfach, es separat von unique_ptr selbst zu implementieren. (Wie in den Kommentaren erwähnt, müssen Sie sicherstellen, dass ein geeigneter Deleter für den Allokator verwendet wurde. Der Standardlöscher würde delete verwenden und furchtbar falsch gehen).

Dies scheint wie eine offensichtliche Redewendung.

In der Tat. Aber auch viele andere Idiome, und nicht alles kann (oder sollte) standardisiert werden.

Für eine offizielle Begründung des aktuellen Fehlens von allocate_unique, siehe proposal for make_unique, speziell Abschnitt 4 (Custom Deleter).

+3

+1. Der im Vorschlag erwähnte Typlöschungsaspekt ist IMHO am wichtigsten, welcher Typ würde 'allocate_unique' zurückgeben? –

+0

@ JonathanWakely: Guter Punkt. Vielleicht könnte sich meine Behauptung, dass es "einigermaßen geradlinig" sei, ändern, wenn ich es tatsächlich versuchen würde. –

12

Muss ich den Puffer selbst zuweisen und dann einem unique_ptr zuweisen?

Nicht nur ein Puffer, ein Zeiger auf ein Objekt. Möglicherweise muss das Objekt jedoch vom Zuordner zerstört werden, und der Speicher muss definitiv vom Zuordner freigegeben werden. Daher müssen Sie auch den Zuweiser unique_ptr übergeben. Es ist nicht in der Lage, einen Zuordner zu verwenden, daher müssen Sie ihn in einen benutzerdefinierten Löschdienst einfügen, der Teil des Typs unique_ptr wird.

Ich denke, eine generische Lösung wie folgt aussehen würde:

#include <memory> 

template<typename Alloc> 
struct alloc_deleter 
{ 
    alloc_deleter(const Alloc& a) : a(a) { } 

    typedef typename std::allocator_traits<Alloc>::pointer pointer; 

    void operator()(pointer p) const 
    { 
    Alloc aa(a); 
    std::allocator_traits<Alloc>::destroy(aa, std::addressof(*p)); 
    std::allocator_traits<Alloc>::deallocate(aa, p, 1); 
    } 

private: 
    Alloc a; 
}; 

template<typename T, typename Alloc, typename... Args> 
auto 
allocate_unique(const Alloc& alloc, Args&&... args) 
{ 
    using AT = std::allocator_traits<Alloc>; 
    static_assert(std::is_same<typename AT::value_type, std::remove_cv_t<T>>{}(), 
       "Allocator has the wrong value_type"); 

    Alloc a(alloc); 
    auto p = AT::allocate(a, 1); 
    try { 
    AT::construct(a, std::addressof(*p), std::forward<Args>(args)...); 
    using D = alloc_deleter<Alloc>; 
    return std::unique_ptr<T, D>(p, D(a)); 
    } 
    catch (...) 
    { 
    AT::deallocate(a, p, 1); 
    throw; 
    } 
} 

int main() 
{ 
    std::allocator<int> a; 
    auto p = allocate_unique<int>(a, 0); 
    return *p; 
} 
+0

@LucDanton, ich rollte Ihre Bearbeitung zurück, ich entschied mich eher abzulehnen als sehr explizit zu binden. 'allocate_shared' muss sowieso neu binden, also spielt es keine Rolle, aber hier stimmt das nicht. Wenn Container den richtigen value_type benötigen, dann kann auch mein 'allocate_unique' impl :-) –

+0

Danke Jonathan. Ich habe über meine ACCU-Notizen nachgedacht, anstatt in letzter Zeit viel zu programmieren, aber ich habe diesen Code an drei Stellen ohne Zwischenfälle verwendet, so dass er vorläufig das Hatcat-Gütesiegel erhält. – hatcat

+0

@hatcat, cool, froh, dass es funktioniert. Danke für deine Blitzreden bei ACCU, es hat mich daran erinnert, wie sehr ich Isolation spielen möchte. –

Verwandte Themen