2012-11-29 9 views
17

sagen, dass ich den folgenden Code in einem C++ Programm:Was bedeutet "neuer (& variabler) Wert;" in C++ tun?

Object a = Object(someParameters); 
new (&a) Object(someOtherParameters); 

Meine Vermutung ist, dass es den Inhalt von a mit Object(someOtherParameters) ersetzt, was eine mögliche operator= für Object erklärt zu vermeiden. Ist das richtig?

+2

Neben den vorhandenen Antworten: Die Syntax im * title * Ihrer Frage existiert nicht! Sie können diese Syntax nicht mit einem beliebigen Wert verwenden, Sie können sie einfach in einem Konstruktoraufruf verwenden - d. H. "Wert" muss die Form "T (Argumente)" haben. –

+0

Platzierung neu immer in einem C++ - Speicherpool (Objekte Pool) verwendet. als zusätzliche Antwort. – Healer

Antwort

21

Es heißt placement new. Es ruft den Konstruktor im angegebenen Speicher auf, anstatt neuen Speicher zuzuweisen. Beachten Sie, dass Sie in diesem Fall den Destruktor Ihres Objekts explizit aufrufen müssen, bevor Sie den zugewiesenen Speicher freigeben können.

Klärung. Angenommen, Sie haben einen unformatierten Speicher

zugewiesen, und Sie möchten ein Objekt in diesem Speicher erstellen. Sie rufen

new(rawMemory) Object(params); 

Nun, bevor die Speicherfreigabe

delete [] rawMemory; 

Sie das derstuctor von Object explizit

reinterpret_cast<Object*>(rawMemory)->~Object(); 

In Ihrem speziellen Beispiel haben zu rufen, aber das potenzielle Problem ist dass Sie das vorhandene Objekt nicht ordnungsgemäß zerstört haben, bevor Sie ein neues in seinem Speicher erstellt haben.

Bonus: Haupt gewundert, wie Standard std::vector ohne die darin enthaltenen Objekte sind default-konstruierbar tun kann? Der Grund ist, dass bei den meisten, wenn nicht allen, Implementierungen allocator<T> keine T* p speichert, die erfordern würden, dass T im Fall von p = new T[N] standardmäßig konstruierbar ist. Stattdessen speichert es einen char Zeiger - Raw-Speicher und weist p = new char[N*sizeof(T)] zu. Wenn Sie ein Objekt push_back aufrufen, ruft es einfach den Kopierkonstruktor mit der neuen Position an der entsprechenden Adresse in diesem char-Array auf.

+0

Der letzte Satz ist verwirrend/falsch: Der Destruktor wird automatisch am Ende des Bereichs aufgerufen, bevor der Speicher des Objekts freigegeben wird. Aber der Destruktor für das * zuvor existierende * Objekt muss vor dem Überschreiben aufgerufen werden. Für eine bessere Güte sollte diese Antwort auch die Möglichkeit der Überlastung des Bedieners erwähnen - möglicherweise führt eine Überladung etwas völlig anderes aus. –

+2

@KonradRudolph: Nein, ist es nicht. 'Class * object = new (rawMemory) Klasse (params);' Sie können später 'delete object;' nicht aufrufen, weil der Speicher nicht durch 'new' zugewiesen wurde. Daher müssen Sie 'object-> ~ Class()' explizit aufrufen, bevor Sie 'delete [] rawMemory' aufrufen. –

+0

Das Objekt in der Frage von OP ist Stapel-zugeteilt und des richtigen Typs, so dass Ihr Einwand nicht gilt.Selbst für dynamisch zugewiesenen Speicher können Sie sehr gut folgendes tun: 'T * x = new T; x-> ~ T(); neu (x) T(); delete x; '(beachten Sie die Reihenfolge von Destruktor-Aufruf und Platzierung neu!) –

6

Es ist bekannt als Platzierung neu: es baut das neue Object an der Adresse innerhalb der Klammern angegeben. Platzierung neu wird normalerweise verwendet, um ein Objekt im Rohspeicher zu erstellen. Ein neues Objekt über einem vorhandenen zu konstruieren, wie dies der Code tut, ist eine schlechte Idee, weil es den Destruktor für das ursprüngliche Objekt nicht aufruft.