陣列的新放置:可移植性問題
在 C 中,新放置允許在指定位址分配記憶體。然而,它在陣列中的使用帶來了可移植性的挑戰。本文探討了這個問題並提出了一個可移植的解決方案。
通常假設 new[] 傳回的指標與提供的位址一致。然而,C 標準(5.3.4,註 12)顯示情況可能並非如此。當嘗試使用放置 new 為陣列分配緩衝區時,這會帶來問題。
以下程式碼示範了此問題:
#include <new> #include <stdio.h> class A { public: A() : data(0) {} virtual ~A() {} int data; }; int main() { const int NUMELEMENTS = 20; char* pBuffer = new char[NUMELEMENTS * sizeof(A)]; A* pA = new(pBuffer) A[NUMELEMENTS]; printf("Buffer address: %x, Array address: %x\n", pBuffer, pA); delete[] pBuffer; // Assertion failure due to heap corruption return 0; }
對記憶體的檢查表明,某些編譯器(例如, Visual Studio)在數組之前分配額外的位元組以進行內部簿記(例如,數組元素的計數)。這可能會導致堆損壞。
問題出現了:我們能否確定與不同編譯器的陣列的放置 new 相關的開銷?我們的目標是找到一個可移植的解決方案。
建議的解
與其在整個陣列上使用placement new,一個可能的解決方法是單獨分配每個陣列元素:
int main(int argc, char* argv[]) { 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(); } printf("Buffer address: %x, Array address: %x\n", pBuffer, pA); // Manual destruction for (int i = 0; i < NUMELEMENTS; ++i) { pA[i].~A(); } delete[] pBuffer; return 0; }
此方法明確控制陣列中每個物件的放置,並確保正確執行銷毀。
結論
使用放置new 陣列需要仔細考慮編譯器特定的開銷。所提出的解決方案透過單獨分配和銷毀數組元素提供了一種可移植的替代方案。
以上是陣列的放置新功能在 C 中真的可以移植嗎?的詳細內容。更多資訊請關注PHP中文網其他相關文章!