Placement portable nouveau pour les tableaux
L'opérateur de placement new de la bibliothèque standard permet l'allocation de mémoire à une adresse spécifiée. Cependant, son utilisation avec des tableaux soulève des problèmes de portabilité en raison de divergences potentielles entre le pointeur renvoyé et l'adresse transmise.
Comprendre le problème
Lors de l'utilisation du placement new pour tableaux, le pointeur renvoyé peut ne pas s’aligner sur l’adresse fournie. Ceci est expliqué dans la note 12 du 5.3.4 de la norme C. Par conséquent, l'allocation d'un tampon spécifiquement pour le tableau devient problématique.
Considérez l'exemple suivant :
#include <iostream> #include <new> class A { public: A() : data(0) {} ~A() {} int data; }; int main() { const int NUMELEMENTS = 20; char *pBuffer = new char[NUMELEMENTS * sizeof(A)]; A *pA = new(pBuffer) A[NUMELEMENTS]; // Output may show pA as four bytes higher than pBuffer std::cout << "Buffer address: " << pBuffer << ", Array address: " << pA << std::endl; delete[] pBuffer; return 0; }
Cet exemple entraîne souvent une corruption de la mémoire sous Microsoft Visual Studio. L'examen de la mémoire révèle que le compilateur préfixe l'allocation du tableau avec quatre octets, stockant probablement le nombre d'éléments du tableau. Ce comportement varie en fonction du compilateur et de la classe utilisée.
Solution portable
Pour résoudre ce problème de portabilité, évitez d'utiliser le placement new directement sur les tableaux. Au lieu de cela, envisagez d'allouer chaque élément du tableau individuellement à l'aide du placement new :
#include <iostream> #include <new> class A { public: A() : data(0) {} ~A() {} int data; }; int main() { const int NUMELEMENTS = 20; char *pBuffer = new char[NUMELEMENTS * sizeof(A)]; A *pA = (A*)pBuffer; for (int i = 0; i < NUMELEMENTS; ++i) { pA[i] = new (pA + i) A(); } std::cout << "Buffer address: " << pBuffer << ", Array address: " << pA << std::endl; // Remember to manually destroy each element for (int i = 0; i < NUMELEMENTS; ++i) { pA[i].~A(); } delete[] pBuffer; return 0; }
Quelle que soit l'approche adoptée, il est crucial de détruire manuellement chaque élément du tableau avant de supprimer le tampon pour éviter les fuites de mémoire.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!