Quelle est cette deuxième nouvelle?

Quelle est la deuxième ligne? (Vu en répondant à une autre question.)

int * x = new int [1] ; int * y = new (x) int; 

Après la deuxième ligne, x et y ont la même valeur (pointez au même endroit). Quelle est la différence entre y = x et la deuxième ligne? Est-ce comme un constructeur ou quelque chose comme ça?

C’est un placement nouveau . Il construit un nouvel int dans la mémoire indiquée par x .

Si tu essayes:

 int * x = new int [1]; *x = 5; std::cout << *x << std::endl; int * y = new (x) int; *y = 7; std::cout << *x << std::endl; 

la sortie sera:

 5 7 

Ceci est appelé placement nouveau . Il vous permet de construire un object en mémoire déjà alloué.

Ce fil de discussion précédent explique où et comment il est utile .

Le deuxième nouveau est un “placement nouveau”. Il effectue l’initialisation (c’est-à-dire appelle tous les constructeurs nécessaires) sans aucune allocation. C’est utile lorsque vous devez créer un schéma d’allocation de mémoire personnalisé.

C’est un nouveau placement.

Bien que vous ne l’utilisiez pas habituellement avec des types entiers.
Il est généralement utilisé pour créer un tampon dans lequel vous construisez ensuite d’autres types.

 // Allocate a buffer with enough room for two T objects. char* buffer = new char[sizeof(T) * 2]; // Allocate a T in slot zero T* t1 = new (buffer + 0 * sizeof(T)) T("Zero"); // Allocate a T in slot one T* t2 = new (buffer + 1 * sizeof(T)) T("One"); 

Thats les bases.
Mais rappelez-vous que les objects alloués avec placement new ne peuvent pas être supprimés avec l’instruction delete . En effet, delete tente de récupérer la mémoire allouée par new (ainsi que d’appeler le destructeur). Donc, pour utiliser ces objects correctement, vous devez appeler manuellement leur destructeur.

 t1->~T(); t2->~T(); 

N’oubliez pas de supprimer le tampon d’origine.

 delete [] buffer; 

Quelques autres mises en garde:
Les gens voient souvent que le tampon pourrait être implémenté sur la stack et ainsi être automatiquement libéré

 char buffer[sizeof(T) * 2]; 

Malheureusement, cela peut être techniquement correct (comstack). Mais son fonctionnement n’est pas garanti, car la mémoire tampon peut ne pas être alignée correctement pour que le T soit placé à l’intérieur. Vous devez donc allouer le tampon dynamicment (en utilisant new, il garantit que la mémoire est alignée correctement pour tout object de la taille allouée (ainsi, par extension, elle est également alignée pour toute taille inférieure à la taille allouée). ce problème est d’utiliser un std :: vector

 std::vector buffer(sizeof(T) * 2); T* t1 = new (&buffer[0] + 0 * sizeof(T)) T("Zero"); T* t2 = new (&buffer[0] + 1 * sizeof(T)) T("One"); 

Une autre utilisation de placement new consiste à réinitialiser un object.
J’ai déjà vu cela, mais je préfère utiliser l’opérateur d’affectation plus standard:

 T obj1("Plop"); obj1 = T("Another Plop"); // Can be done like this: T obj1("Plop"); obj1.~T(); new (&obj1) T("Another Plop"); // Seems excessive to me. But can be us-full // in some extreme situations. 

N’oubliez pas que si vous utilisez la méthode de réinitialisation, vous devez d’abord détruire l’ancien object (sinon l’object pourrait ne pas se comporter correctement).

 int * y = new (x) int; 

C’est comme par nouvelle syntaxe de placement.

EDIT: Parallèlement à l’allocation personnalisée, le placement new permet également de réinitialiser un état d’object comme ci-dessous.

 class Test { int startVal; public: Test() { startVal = 1; } void setVal(int val) { startVal = val; } }; int main() { Test *p = new Test; //Creates new object and initializes it with //a call to constructor. p->setVal(10); //Change object content. new(p) Test; //Reset object: //object pointed by p will be re-initialzed here by making //a call to constructor. startVal will be back to 1 } 

Comme décrit dans les commentaires ci-dessus, la réinitialisation de l’état de l’object peut également être effectuée à l’aide du placement new. placement new n’alloue pas de mémoire, il construit un object à l’adresse spécifiée dans la parenthèse.