/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++ 标准。 如果你实现运算符 newdelete 的唯一原因是支持过度对齐的分配,则在 C++17 或之后的模式中可能不再需要此代码。 要关闭此选项并在使用 /std::c++17 或更高版本时恢复到 newdelete 的 C++14 行为,请指定 /Zc:alignedNew-。 如果实现运算符 newdelete,但未准备好实现具有 align_val_t 参数的过度对齐的运算符 newdelete 重载,请使用 /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 开发环境中设置此编译器选项

  1. 打开项目的“属性页” 对话框。 有关详细信息,请参阅在 Visual Studio 中设置 C++ 编译器和生成属性

  2. 选择“配置属性”>“C/C++”>“命令行”属性页

  3. 修改“附加选项”属性以包含 /Zc:alignedNew/Zc:alignedNew-,然后选择“确定”

另请参阅

/Zc(一致性)