陣列的可移植放置新功能
標準庫的放置新運算子允許在指定位址分配記憶體。然而,由於傳回的指標和傳入的位址之間可能存在差異,它與陣列一起使用會引起對可移植性的擔憂。
理解問題
使用placement new時數組,傳回的指標可能與提供的位址不一致。 C 標準 5.3.4 的註 12 對此進行了解釋。因此,專門為數組分配緩衝區會出現問題。
請考慮以下範例:
#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; }
此範例通常會導致 Microsoft Visual Studio 下的記憶體損壞。對記憶體的檢查表明,編譯器在數組分配前添加了四個字節,可能存儲數組元素的計數。此行為因所使用的編譯器和類別而異。
可移植解決方案
要解決此可移植性問題,請避免直接在陣列上使用放置 new。相反,請考慮使用放置 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; }
無論採用哪種方法,在刪除緩衝區之前手動銷毀每個數組元素對於防止記憶體洩漏至關重要。
以上是在 C 數組上使用佈局是可移植的新功能嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!