Можно ли фактически использовать размещение нового в переносимом коде при использовании его для массивов?
Похоже, что указатель, который вы получаете от new [], не всегда совпадает с адресом, который вы передаете (5.3.4, примечание 12 в стандарте, кажется, подтверждает, что это правильно), но я Посмотрите, как вы можете выделить буфер для массива, если это так.
В следующем примере показана проблема. Этот пример, скомпилированный с Visual Studio, приводит к повреждению памяти:
#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];
// With VC++, pA will be four bytes higher than pBuffer
printf("Buffer address: %x, Array address: %x\n", pBuffer, pA);
// Debug runtime will assert here due to heap corruption
delete[] pBuffer;
return 0;
}
Глядя на память, кажется, что компилятор использует первые четыре байта буфера для хранения количества элементов в нем. Это означает, что, поскольку размер буфера составляет всего sizeof(A)*NUMELEMENTS
, последний элемент в массиве записывается в нераспределенную кучу.
Итак, вопрос в том, можете ли вы выяснить, сколько дополнительных затрат требует ваша реализация для безопасного использования размещения new []? В идеале мне нужна техника, которая переносима между разными компиляторами. Обратите внимание, что, по крайней мере в случае VC, накладные расходы различаются для разных классов. Например, если я удаляю виртуальный деструктор в примере, адрес, возвращаемый из new [], совпадает с адресом, который я передаю.