当浏览 operator new,operator new[] - cppreference.com 时,我们似乎有很多选项可以用于分配具有特定对齐要求的对象数组。但是,没有指定如何使用它们,而且我似乎找不到正确的 C++ 语法。
我可以以某种方式显式调用此运算符,还是编译器会自动推断重载? :
void* operator new[]( std::size_t count, std::align_val_t al );
查看Bartek的编码博客,似乎编译器会根据对齐要求是否大于
__STDCPP_DEFAULT_NEW_ALIGNMENT__
(在64位机器上通常为16)自动选择重载。
在某些情况下是否可以手动为
new
运算符选择重载?有时我可能希望分配的块以某种方式对齐(我假设对齐始终是 2 的幂,并且可能大于 16)。
在可预见的未来,我可能会使用 GCC 和 C++ >= 17。
operator new
的附加参数在类型之前的括号内传递:
#include <new>
int* allocate() {
return new (std::align_val_t(16)) int[40]; // 128-bit alignment
// will call `void* operator new[](size_t, align_val_t)`
}
看来我来晚了一点:)
但是由于我也偶然发现了这个话题并提出了同样的问题,所以觉得有必要澄清一下
所以问题是,编译器似乎足够聪明,只有当它看到具有
new
对齐要求的类型时,即比 STDCPP_DEFAULT_NEW_ALIGNMENT更对齐时,才能达到所述
special
的重载。
(cppreference 上的第 3,4 点)
- 由 new 调用,为对齐要求超过STDCPP_DEFAULT_NEW_ALIGNMENT的单个对象分配所需的存储空间。
- 由 new[] 调用,为对齐要求超过 STDCPP_DEFAULT_NEW_ALIGNMENT 的对象数组分配所需的所有存储空间。
这里(以及这里)是一个片段,表明它确实发生了:
#include <iostream>
void* operator new ( std::size_t count, std::align_val_t al ) {
std::cerr << "aligned alloc call with alignment=" << (std::size_t)al << " and count=" << count << std::endl;
return ::operator new (count); ///< definitely not a good idea, but ok for this purpose
}
struct alignas(32) Overaligned {};
int main() {
Overaligned* op = new Overaligned{};
std::cerr << (const void*)op; // here just so that the compiler doesn't optimize away everything :)
}
所以是的,它会调用它:) 但如果您愿意,您可以手动分配内存,然后将东西放在那里:
::operator new[](sizeof(YourType), align_val_t{alignof(YourType)})