2016-02-10 6 views
5

Mit der Platzierung neue Syntax platziert worden ist, sollte ich in der Lage sein, so etwas zu tun:Wie zu bestimmen, ob Objekt mit Platzierung neuer

char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer 
MyClass *my_class = new (buffer) MyClass; //put da class there 

Nun nehmen wir an ich nur die erste Zeile, aber nicht die zweite . Gibt es eine Möglichkeit, dass im Code festgestellt werden kann, ob der Puffer entsprechend zugeordnet wurde, aber dort noch kein Objekt vom Typ MyClass instanziiert wurde?

+2

Warum brauchen Sie das? Es scheint nicht richtig zu sein. – ZDF

+0

@ZDF Wie sich herausstellt, als ich das Problem genauer betrachtete, stellt sich heraus, dass ich es wahrscheinlich nicht tue. Also die Antwort auf Ihre Frage scheint ziemlich klar - Unerfahrenheit ... :) – Bitrex

Antwort

1

Originalcode:

char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer 
MyClass *my_class = new (buffer) MyClass; //put da class there 

Um zu bestimmen, dynamisch, ob die Platzierung new hat Informationen durchgeführt wurde darüber irgendwo gespeichert werden muss. Die Sprache bietet diesen Dienst nicht an. Also müssen Sie es selbst tun, in einer von zwei möglichen Hauptarten:

  • Speichern der Informationen im Puffer.
    In diesem Fall muss der Puffer bei der Zuweisung initialisiert werden. Z.B. Fügen Sie einfach () am Ende Ihres Ausdrucks new hinzu. Andernfalls kann nicht garantiert werden, dass der Inhalt des Puffers nicht wie ein Objekt aussieht. Zwei Unterfälle:
    1. Durch Hinzufügen von Platz für eine Flagge im Puffer.
    2. Durch die Flagge als Mitglied des Objekts.
      Im Fall einer polymorphen Klasse wird es in der Praxis einen von Null verschiedenen Vtable-Zeiger geben, der als Flag dienen kann.
  • Speichern der Informationen extern.
    In diesem Fall muss der Puffer bei der Zuweisung nicht initialisiert werden.Es gibt eine Zillion plus einige Möglichkeiten, einschließlich
    1. Eine einfache bool Variable.
    2. Eine Sammlung von Zeigern für alle diese Objekte.
    3. Ein akustisches Signal an einen Schimpansen, der später abgefragt wird.
4

Die Sprache bietet keinen eingebauten Mechanismus, um diese Informationen zu liefern, zumindest keine, die ich kenne. Sie müssen Ihren eigenen Buchhaltungscode hinzufügen, um solche Informationen zu verfolgen.

1

Sie könnten eine static Tabelle mit this Zeigerwerten verwalten, die Sie in den Konstruktoren und dem Destruktor zu MyClass mutieren. Dann überprüfen Sie dies gegen einen bestimmten Wert von buffer, wenn Sie müssen.

Vergessen Sie nicht, die Auswirkungen der Bewegungssemantik zu berücksichtigen. Wird schwierig sein, um richtig zu werden.

2

Für Debugging-Zwecke können Sie ein spezielles Element signature-MyClass und setzen Sie den Wert auf einen konstanten

class MyClass { 
    public: 
     MyClass() : signature(762347562374) {} 
     bool isValidSignature() const { return signature==762347562374; } 
    private: 
     unsigned long long signature; 
     <other members> 
}; 

Dann überprüfen Sie es wie folgt hinzufügen:

char *buffer = new char[sizeof(MyClass)]; //pre-allocated buffer 
MyClass *my_class = new (buffer) MyClass; //put da class there 
if (my_class->isValidSignature()) 
    <this means that the object has been allocated correctly, with a high probability> 
} 

können Sie alles setzen, das ist im Zusammenhang mit der Signatur, in einem richtigen #ifdef, so dass nur im Debug-Modus ausgeführt wird.

+0

Warum sollte man statistische Ansatz verwenden, wenn eine Flagge garantiertes Verhalten liefert? –

+0

@ Cheersandthth.-Alf Es scheint, dass es eine triviale Lösung für das Problem gibt, über das Sie sprechen. Ich verstehe es nicht; Vielleicht sollten Sie eine Antwort hinzufügen, um zu erklären, was Sie unter "Flagge" verstehen. – anatolyg

+0

Ich hasse Klassen, die eine andere (größere) Größe in Debug-Builds haben –

1

Nicht ohne selbst zu verfolgen. Eine Lösung wäre, einen Wrapper um std::allocator zu erstellen.

template<class T> 
class MyAllocator 
{ 
public: 
    T* allocate(std::size_t count = 1) 
    { 
     return allocator_.allocate(count); 
    } 

    template<class... Args> 
    void construct(T* ptr, Args&&... args) 
    { 
     allocator_.construct(ptr, std::forward<Args>(args)...); 
     allocated_ = true; 
    } 

    bool IsAllocated() const 
    { 
     return allocated_; 
    } 

private: 
    std::allocator<T> allocator_; 
    bool allocated_; 

}; 
+0

Wie vergleicht das direkt mit einer 'Bool'-Variablen? –

+0

Ich dachte nur, es war eine gute Möglichkeit, die Dinge abzuschließen. –

Verwandte Themen