/Zc:alignedNew
(C++17 过度对齐分配)
启用对 C++17 过度对齐的 new
的支持,它是一种在大于最大标准对齐类型 max_align_t
的默认值的边界对齐的动态内存分配。
语法
]$
备注
MSVC 编译器和库支持 C++17 标准过度对齐的动态内存分配。 指定了 /Zc:alignedNew
选项时,new Example;
等动态分配遵守 Example
的对齐,即使它大于任何基本类型所需的最大对齐 max_align_t
也是如此。 当已分配类型的对齐仅仅是原始运算符 new
(作为预定义宏 __STDCPP_DEFAULT_NEW_ALIGNMENT__
的值提供)保证的对齐时,语句 new Example;
会导致对 ::operator new(size_t)
的调用,正如它在 C++14 中所做的一样。 当对齐大于 __STDCPP_DEFAULT_NEW_ALIGNMENT__
时,实现改为使用 ::operator new(size_t, align_val_t)
获取内存。 同样,删除过度对齐的类型会调用 ::operator delete(void*, align_val_t)
或特定大小的删除签名 ::operator delete(void*, size_t, align_val_t)
。
/Zc:alignedNew
选项仅在启用 /std:c++17
或更高版本时才可用。 在 /std:c++17
或更高版本的情况下,默认启用 /Zc:alignedNew
以符合 C++ 标准。 如果你实现运算符 new
和 delete
的唯一原因是支持过度对齐的分配,则在 C++17 或之后的模式中可能不再需要此代码。 要关闭此选项并在使用 /std::c++17
或更高版本时恢复到 new
和 delete
的 C++14 行为,请指定 /Zc:alignedNew-
。 如果实现运算符 new
和 delete
,但未准备好实现具有 align_val_t
参数的过度对齐的运算符 new
和 delete
重载,请使用 /Zc:alignedNew-
选项防止编译器和标准库生成对过度对齐的重载的调用。 /permissive-
选项不会更改的 /Zc:alignedNew
默认设置。
从 Visual Studio 2017 版本 15.5 开始提供对 /Zc:alignedNew
的支持。
示例
此示例显示设置 /Zc:alignedNew
选项时运算符 new
和运算符 delete
的行为方式。
// alignedNew.cpp
// Compile by using: cl /EHsc /std:c++17 /W4 alignedNew.cpp
#include <iostream>
#include <malloc.h>
#include <new>
// "old" unaligned overloads
void* operator new(std::size_t size) {
auto ptr = malloc(size);
std::cout << "unaligned new(" << size << ") = " << ptr << '\n';
return ptr ? ptr : throw std::bad_alloc{};
}
void operator delete(void* ptr, std::size_t size) {
std::cout << "unaligned sized delete(" << ptr << ", " << size << ")\n";
free(ptr);
}
void operator delete(void* ptr) {
std::cout << "unaligned unsized delete(" << ptr << ")\n";
free(ptr);
}
// "new" over-aligned overloads
void* operator new(std::size_t size, std::align_val_t align) {
auto ptr = _aligned_malloc(size, static_cast<std::size_t>(align));
std::cout << "aligned new(" << size << ", " <<
static_cast<std::size_t>(align) << ") = " << ptr << '\n';
return ptr ? ptr : throw std::bad_alloc{};
}
void operator delete(void* ptr, std::size_t size, std::align_val_t align) {
std::cout << "aligned sized delete(" << ptr << ", " << size <<
", " << static_cast<std::size_t>(align) << ")\n";
_aligned_free(ptr);
}
void operator delete(void* ptr, std::align_val_t align) {
std::cout << "aligned unsized delete(" << ptr <<
", " << static_cast<std::size_t>(align) << ")\n";
_aligned_free(ptr);
}
struct alignas(256) OverAligned {}; // warning C4324, structure is padded
int main() {
delete new int;
delete new OverAligned;
}
对于 32 位版本来说,此输出非常典型。 指针值根据应用程序在内存中运行的不同位置而有所不同。
unaligned new(4) = 009FD0D0
unaligned sized delete(009FD0D0, 4)
aligned new(256, 256) = 009FE800
aligned sized delete(009FE800, 256, 256)
有关 Visual C++ 中一致性问题的信息,请参阅非标准行为。
在 Visual Studio 开发环境中设置此编译器选项
打开项目的“属性页” 对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性。
选择“配置属性”>“C/C++”>“命令行”属性页。
修改“附加选项”属性以包含
/Zc:alignedNew
或/Zc:alignedNew-
,然后选择“确定”。