2017-05-12 1 views
2

Ich lese this post über die Verwendung von Placement neu, um eine boost::shared_ptr zurückgesetzt, während zusätzliche Speicherzuweisungen zu vermeiden, und davon ausgehen, dass das gleiche, wenn nicht ähnlich, für eine std::unique_ptr getan werden kann? Meine Frage ist, wenn die std::unique_ptr vom Typ Base* ist und so auf jede Derived* zeigen kann, wird die placement new wie beabsichtigt funktionieren, wenn die Derived Klassen in der Größe variieren? So etwas wie diese vielleicht:Verwenden der Platzierung neu für eine polymorphe unique_ptr

class Base 
{ 
public: 
    Base() {} 
    virtual ~Base(){} 
}; 

class Foo : public Base 
{ 
public: 
    Foo() : Base() {} 
    virtual ~Foo(){} 
    int a; 
    int b; 
}; 

class Bar : public Base 
{ 
public: 
    Bar() : Base() {} 
    virtual ~Bar() {} 
    int a; 
}; 

int main() 
{ 
    std::unique_ptr<Base> bp(new Bar()); 
    bp->~Base(); //edit: call destructor 
    void* rawP = dynamic_cast<void*>(bp.release());//edit: cast to void* 
    bp.reset(new(rawP) Foo()); 
    return 0; 
} 
+0

Beachten Sie, dass Sie den Destruktoraufruf für das ursprüngliche 'Bar'-Objekt verpassen. –

+0

Also das Überschreiben des Speichers, der das 'Bar'-Objekt enthält, beseitigt nicht die Notwendigkeit, es Destruktor zu nennen? – nitronoid

+1

Das ist im Prinzip besorgniserregend: Der zurückgegebene 'Base'-Zeiger zeigt möglicherweise nicht auf den Anfang der Zuweisung. Zumindest sollten Sie die reale Adresse über 'dynamic_cast (rawP)' erhalten. –

Antwort

5

Das wird nicht funktionieren. Ein Objekt Foo ist einfach zu groß, um in den Speicher zu passen, der für ein Objekt Bar reserviert ist. Wenn Sie möchten, dass bp auf ein Foo Objekt zeigt, müssen Sie genügend Speicherplatz für einen zuweisen.

Platzierung neu erstellt ein Objekt im Speicher, das Sie bereits besitzen. Es liegt an Ihnen, sicherzustellen, dass der Speicher groß genug ist, um das Objekt, das Sie konstruieren, zu halten.

+0

Also, wenn alle meine abgeleiteten Objekte die gleiche Größe haben, würde es funktionieren? Würden wir auch einen Weg finden, den bereits zugewiesenen Speicher zu nutzen, und wie viel mehr benötigt wird, anstatt einen völlig neuen Block zuweisen zu müssen? – nitronoid

+0

@nitronoid Ich würde erwarten, dass es funktionieren würde, wenn alle abgeleiteten Klassen die gleiche Größe haben. Wahrscheinlich möchten Sie auf "void *" umwandeln, um sicherzustellen, dass Sie auf den Anfang Ihres Speicherblocks zeigen, wie von @KerrekSB in den Kommentaren erwähnt. Außerdem gibt es keine Möglichkeit, ein Objekt über zwei Speicherblöcke zu verteilen. –

+0

@nitronoid Sobald ein Block Speicher für ein Objekt zugewiesen wurde, gibt es keine Möglichkeit, diesen Block größer zu machen. –

Verwandte Themen