17

私の質問はかなり単純です。

alignas指定子は「new」で動作しますか?つまり、構造体が整列するように定義されている場合、newで割り当てられたときに整列されますか?

4

2 に答える 2

16

C ++ 17より前では、タイプの配置が過剰に配置されていない場合は、はい、デフォルトnewが機能します。「オーバーアラインメント」とは、指定したアラインメントが。alignasより大きいことを意味しますalignof(std::max_align_t)。デフォルトnewは、多かれ少なかれ偶然にオーバーアラインされていないタイプで機能します。デフォルトのメモリアロケータは、常に。に等しい配置でメモリを割り当てますalignof(std::max_align_t)

ただし、タイプの配置が過剰に配置されている場合は、運が悪いです。デフォルトnewも、作成するグローバルnew演算子も、その型に必要な配置を知ることはできず、それに適切なメモリを割り当てることもできません。このケースを支援する唯一の方法は、クラスのをオーバーロードすることです。これにより、。operator newを使用してクラスの配置を照会できますalignof

もちろん、そのクラスが別のクラスのメンバーとして使用されている場合、これは役に立ちません。他のクラスもオーバーロードしない限り、そうではありませんoperator new。だから、new pair<over_aligned, int>()うまくいかないほど単純なもの。

C ++ 17は、使用されているタイプのアラインメントが与えられる多数のメモリアロケータを追加します。これらのアロケータは、特にオーバーアラインされたタイプ(またはより具体的には、新しく拡張されたオーバーアラインされたタイプ)に使用されます。したがってnew pair<over_aligned, int>()、C++17で動作します。

もちろん、これはアロケータがオーバーアラインされたタイプを処理する範囲でのみ機能します。

于 2013-03-19T23:03:57.037 に答える
15

いいえ、違います。構造体は要求された位置合わせにパディングされますが、位置合わせされません。ただし、これはC ++ 17で許可される可能性があります(このC ++ 17提案が存在するという事実は、これがC ++ 11では機能しないことのかなり良い証拠になるはずです)。

私はこれがいくつかのメモリアロケータで動作するように見えるのを見ましたが、それは純粋な運でした。たとえば、一部のメモリアロケータは、アロケータの最適化として、メモリ割り当てを要求されたサイズの2の累乗(最大4KB)に調整します(メモリの断片化を減らし、以前に解放されたメモリの再利用を容易にするなど)。 。ただし、テストしたOS X10.7およびCentOS6システムに含まれている新しい/malloc実装はこれを行わず、次のコードで失敗します。

#include <stdlib.h>
#include <assert.h>

struct alignas(8)   test_struct_8   { char data; };
struct alignas(16)  test_struct_16  { char data; };
struct alignas(32)  test_struct_32  { char data; };
struct alignas(64)  test_struct_64  { char data; };
struct alignas(128) test_struct_128 { char data; };
struct alignas(256) test_struct_256 { char data; };
struct alignas(512) test_struct_512 { char data; };

int main() {
   test_struct_8   *heap_8   = new test_struct_8;
   test_struct_16  *heap_16  = new test_struct_16;
   test_struct_32  *heap_32  = new test_struct_32;
   test_struct_64  *heap_64  = new test_struct_64;
   test_struct_128 *heap_128 = new test_struct_128;
   test_struct_256 *heap_256 = new test_struct_256;
   test_struct_512 *heap_512 = new test_struct_512;

#define IS_ALIGNED(addr,size)   ((((size_t)(addr)) % (size)) == 0)

   assert(IS_ALIGNED(heap_8, 8));
   assert(IS_ALIGNED(heap_16, 16));
   assert(IS_ALIGNED(heap_32, 32));
   assert(IS_ALIGNED(heap_64, 64));
   assert(IS_ALIGNED(heap_128, 128));
   assert(IS_ALIGNED(heap_256, 256));
   assert(IS_ALIGNED(heap_512, 512));

   delete heap_8;
   delete heap_16;
   delete heap_32;
   delete heap_64;
   delete heap_128;
   delete heap_256;
   delete heap_512;

return 0;
}
于 2015-05-13T23:34:19.010 に答える