我正在构建一个内存分配器,并使用新的位置。 假设我想将10个元素“放置”到堆上已分配的数组中。
首先,常规new在堆上分配必要数量的字节,然后在适当的位置构造WE
对象。
struct WE {
WE() {
std::cout << "WE default constructed\n";
}
~WE() {
std::cout << "WE default destructed\n";
}
double d;
int i;
char c;
};
以下刊登位置用法是否正确?
代码编译和输出似乎正确,但是我有一些疑问。
// 1. allocate
const int elements = 10;
int nbytes = elements * sizeof(WE);
char* memory = new char[nbytes];
WE* pB = (WE*)memory;
int step = sizeof(WE);
// 2. construct
for (int i = 0; i < nbytes; i += step)
new (pB + i) WE();
// 3. process
for (int i = 0; i < nbytes; i += step)
pB[i].i = i * 2;
for (int i = 0; i < nbytes; i += step)
std::cout << '[' << i << ']' << '=' << pB[i].i << '\n';
// 4. destruct
for (int i = 0; i < nbytes; i += step)
pB[i].~WE();
// 5. deallocate
delete[] memory;
pB = nullptr;
memory = nullptr;
如果上述问题都解决了,那么请允许我再问一个问题,如何将这个数组对准任意字节边界?
假设我要对齐sizeof(WE)
的{{1}}(而不是16
的{{1}})。这样的修改:alignof(WE)
是否足以解决问题?我也听说过8
。我不确定它是否可以提供任何好处。 (如果第二个问题使您感到困惑,或者如果我在第1部分中弄乱了,那就算了。)在此先感谢。
答案 0 :(得分:1)
对于对象构造(新放置),您可以按字节/字符迭代:
for (int i = 0; i < nbytes; i += step) new (memory + i) WE();
或逐元素:
for (int i = 0; i < elements; i++) new (pB + i) WE();
在其余循环中,您可以在其中访问元素的地方使用第二个选项。
对于对齐方式,动态内存分配返回一个对齐于alignof(std::max_align_t)
(C ++ 11)的内存块。示例值是16(GCC / x86_64),这是您想要的值,但是标准当然不能保证此值。
如果我没看错,在C ++ 17之前operator new
不能直接为过度对齐的对象分配内存,而std::aligned_storage
在这里没有帮助。从C ++ 17开始,有operator new
的特殊版本可以接受对齐信息,请参阅:https://en.cppreference.com/w/cpp/memory/new/operator_new。