私はこれを読んだアライメントについていつ心配すべきでしょうか?しかし、配置の新しい演算子によって返される、整列されていないポインターについて心配する必要があるかどうかはまだわかりません - 次の例のように:
class A {
public:
long double a;
long long b;
A() : a(1.3), b(1234) {}
};
char buffer[64];
int main() {
// (buffer + 1) used intentionally to have wrong alignment
A* a = new (buffer + 1) A();
a->~A();
}
__alignof(A) == 4
(buffer + 1)
は に揃えられていません。しかし、4
すべて正常に動作します - 完全な例はこちら:http://ideone.com/jBrk8
これがアーキテクチャに依存する場合、私は以下を使用します: linux/powerpc/g++ 4.xx
[更新] この質問を投稿した直後に、この記事を読みました:http://virtrev.blogspot.de/2010/09/memory-alignment-theory-and-c-examples.htmlおそらく、私のケースでの唯一の欠点はパフォーマンスの低下、つまり、アラインされていないアクセスはアラインされているアクセスよりもコストがかかるということでしょうか?
ベストアンサー1
バッファで placement new を呼び出す場合:
A *a = new (buf) A;
void* operator new (std::size_t size, void* ptr) noexcept
次のように定義されている組み込み関数を呼び出します。
18.6.1.3 配置フォーム [new.delete.placement]
これらの関数は予約済みです。C++ プログラムでは、標準 C++ ライブラリ (17.6.4) のバージョンを置き換える関数を定義することはできません。(3.7.4) の規定は、operator new および operator delete のこれらの予約済みの配置形式には適用されません。
void* operator new(std::size_t size, void* ptr) noexcept;
戻り値:ptr
。
備考: 意図的に他のアクションは実行しません。
の(3.7.4)の規定返されるポインタは適切に整列されている必要があるため、void* operator new (std::size_t size, void* ptr) noexcept
非整列ポインタが渡された場合はそれを返しても問題ありません。あなたしかし、それは問題外です。
5.3.4 新しい [expr.new]
[14] 注意:割り当て関数がnull以外の値を返す場合、その値はオブジェクト用のスペースが予約されているストレージブロックへのポインタである必要があります。ストレージブロックは適切に整列され、要求されたサイズであると想定されます。
したがって、位置合わせされていないストレージを配置新しい式に渡すと、ストレージが位置合わせされているという仮定に違反し、結果は UB になります。
実際、上記のプログラムで、 を(after )long long b
に置き換えると、予想どおりプログラムはセグメント違反になります。__m128 b
#include <xmmintrin.h>