GCCのaligned-new警告とgcc -faligned-newオプションに関する詳細情報を見つけるのが困難です。 gcc 7.2.0(--std = c ++ 17なし)でコンパイルし、次のような境界整列構造体を定義しようとします。
_struct alignas(64) Foo { int x; }
_
単純な古いことをするだけです:
_Foo * f = new Foo();
_
次の警告と提案をします。
_ alignas.cpp:36:25: warning: ‘new’ of type ‘Foo’ with extended alignment 64 [-Waligned-new=]
Foo * f = new Foo();
^
alignas.cpp:36:25: note: uses ‘void* operator new(long unsigned int)’, which does not have an alignment parameter
alignas.cpp:36:25: note: use ‘-faligned-new’ to enable C++17 over-aligned new support
_
デフォルトではnew
はalignof( std::max_align_t )
(これは16です)までのメモリのみを返すことを理解していますが、-faligned-newを渡した場合、 gccは、代わりにnew
の適切な新しい配置を強制しますか?
残念ながら、これに関するgccのドキュメントは非常に不足しています。
gcc's manual から:
-faligned-new
_void* ::operator new(std::size_t)
が提供するよりも多くのアライメントを必要とするタイプのC++ 17new
のサポートを有効にします。 -faligned-new = 32などの数値引数を使用して、その関数によって提供されるアライメント(バイト単位)の量を指定できますが、alignof(std::max_align_t)
のデフォルトをオーバーライドする必要があるユーザーはほとんどいません。
これは、-faligned-newが P0035R4 に追加されたaligned-new機能を、C++ 17サポートを完全に有効にしなくても利用できるようにすることを意味します。
C++標準からの関連ビット:
[cpp.predefined]から:
_
__STDCPP_DEFAULT_NEW_ALIGNMENT__
_
値がoperator new(std::size_t)
またはoperator new[](std::size_t)
の呼び出しによって保証されるアラインメントである_std::size_t
_タイプの整数リテラル。 [注:より大きいアライメントはoperator new(std::size_t, std::align_val_t)
などに渡されます(8.3.4)。 —エンドノート]
[basic.align/3]から:
新しい拡張アラインメントは、_
__STDCPP_DEFAULT_NEW_ALIGNMENT__
_より大きいアラインメントで表されます
そして[expr.new/14]から:
オーバーロードの解決は、引数リストを組み立てることによって作成された関数呼び出しで実行されます。最初の引数は要求されたスペースの量であり、タイプは_
std::size_t
_です。割り当てられたオブジェクトの型が新しく拡張された配置を持つ場合、次の引数は型の配置であり、型は_std::align_val_t
_です。
したがって、C++ 17または-faligned-newの場合、Foo
にはnew-extended alignment、Foo* f = new Foo();
はvoid* operator new(size_t, align_val_t)
を呼び出してメモリを割り当て、64バイト境界に適切に配置されたFoo
オブジェクトへのポインターを返します。以前の基準ではそうではありませんでした。