/Zc:alignedNew (C++17 のオーバーアライン割り当て)

最大サイズの標準配置型である max_align_t の既定値を超える境界上で動的メモリ割り当てを行う、C++17 のオーバーアラインの new のサポートを有効にします。

構文

$

解説

MSVC コンパイラとライブラリは、C++17 の標準オーバーアライン動的メモリ割り当てをサポートします。 /Zc:alignedNew オプションが指定されていると、どの基本型でも必要とされる最大の配置である max_align_t を超えていても、new Example; のような動的割り当てで Example の配置が考慮されます。 割り当てられた型の配置が事前定義のマクロ __STDCPP_DEFAULT_NEW_ALIGNMENT__ の値として使用できる元の演算子 new で保証される配置を超えない場合、C++14 と同様、ステートメント new Example; によって ::operator new(size_t) の呼び出しが発生します。 配置が __STDCPP_DEFAULT_NEW_ALIGNMENT__ よりも大きい場合、実装時に代わりに ::operator new(size_t, align_val_t) を使用してメモリが取得されます。 同様に、オーバーアラインされた型の削除によって ::operator delete(void*, align_val_t) またはサイズ設定された delete のシグネチャ ::operator delete(void*, size_t, align_val_t) が呼び出されます。

/Zc:alignedNew オプションは、/std:c++17 以降が有効になっている場合にのみ使用できます。 /std:c++17 以降では、C++ 標準に準拠するために、/Zc:alignedNew が既定で有効になっています。 オーバーアラインされた割り当てをサポートするためだけに newdelete の演算子を実装している場合、このコードは C++17 以降のモードでは不要になる場合があります。 /std::c++17 を使用する場合に、このオプションをオフにし、C++14 の newdelete の動作に戻すには、/Zc:alignedNew- を指定します。 newdelete の演算子を実装したものの、align_val_t パラメーターを持つオーバーアラインされた演算子 newdelete のオーバーロードを実装する準備ができていない場合は、/Zc:alignedNew- オプションを使用してコンパイラと標準ライブラリがオーバーアラインされたオーバーロードに対して呼び出しを行わないようにします。 /permissive- オプションは、/Zc:alignedNew の既定の設定は変更するものではありません。

/Zc:alignedNew のサポートは、Visual Studio 2017 バージョン 15.5 以降で使用できます。

このサンプルは、/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- を含め、[OK] を選択します。

関連項目

/Zc (準拠)