Penempatan Mudah Alih Baharu untuk Tatasusunan
Operator baharu penempatan perpustakaan standard membenarkan peruntukan memori pada alamat yang ditentukan. Walau bagaimanapun, penggunaannya dengan tatasusunan menimbulkan kebimbangan tentang kemudahalihan disebabkan kemungkinan percanggahan antara penuding yang dikembalikan dan alamat yang dihantar masuk.
Memahami Masalah
Apabila menggunakan peletakan baharu untuk tatasusunan, penunjuk yang dikembalikan mungkin tidak sejajar dengan alamat yang diberikan. Ini dijelaskan dalam Nota 12 daripada 5.3.4 piawaian C. Akibatnya, memperuntukkan penimbal khusus untuk tatasusunan menjadi bermasalah.
Pertimbangkan contoh berikut:
#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; }
Contoh ini sering mengakibatkan kerosakan memori di bawah Microsoft Visual Studio. Pemeriksaan memori mendedahkan bahawa pengkompil memberi awalan peruntukan tatasusunan dengan empat bait, mungkin menyimpan kiraan elemen tatasusunan. Tingkah laku ini berbeza-beza bergantung pada pengkompil dan kelas yang digunakan.
Penyelesaian Mudah Alih
Untuk menangani isu mudah alih ini, elakkan menggunakan peletakan baharu secara langsung pada tatasusunan. Sebaliknya, pertimbangkan untuk memperuntukkan setiap elemen tatasusunan secara individu menggunakan peletakan baharu:
#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; }
Tidak kira pendekatan yang diambil, memusnahkan setiap elemen tatasusunan secara manual sebelum memadam penimbal adalah penting untuk mengelakkan kebocoran memori.
Atas ialah kandungan terperinci Adakah Menggunakan Peletakan Baharu pada C Arrays Mudah Alih?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!