Я уверен, что gcc 4.5.2 достаточно стар, что он еще не поддерживает стандартную версию, но C++ 11 добавляет некоторые типы, специально предназначенные для выравнивания - между прочим (std::aligned_storage
и std::aligned_union
) (см. §20.9.7.6 для более подробной информации).
Мне кажется, что наиболее очевидный способ сделать это - использовать реализацию Boost aligned_storage
(или TR1, если у вас есть). Если вы этого не хотите, я все равно буду стараться использовать стандартную версию в большинстве ваших кодов и просто напишу небольшую реализацию для своего собственного использования, пока вы не обновите компилятор, который реализует стандарт. Портативный код, однако, по-прежнему будет немного отличаться от большинства, который использует что-то вроде __declspec(align...
или __attribute__(__aligned__, ...
напрямую.
В частности, он просто дает вам необработанный буфер запрошенного размера с запрошенным выравниванием. тогда вам нужно использовать что-то вроде размещения new для создания объекта вашего типа в этом хранилище.
Для чего это стоит, вот быстрый удар на реализацию aligned_storage
на основе __attribute__(__aligned__,...
директивы ССЗ:
template <std::size_t Len, std::size_t Alignment>
struct aligned_storage {
typedef struct {
__attribute__(__aligned__(Alignment)) unsigned char __data[Len];
} type;
};
Быстрая тестовая программа, чтобы показать, как использовать это:
struct foo {
int a, b, c;
void *operator new(size_t, void *in) { return in; }
};
int main() {
stdx::aligned_storage<sizeof(foo), 8>::type buf;
foo& f = *new (static_cast<void*>(&buf)) foo();
int address = *reinterpret_cast<int *>(&f);
if (address & 0x3 != 0)
std::cout << "Failed.\n";
f.~foo();
return 0;
}
Of Конечно, в реальном использовании вы завершаете/скрываете большую часть уродства, которое я показал здесь. Если вы оставите это так, цена (теоретическая/будущая) переносимость, вероятно, будет чрезмерной.
Мне любопытно; почему имеет значение, что выравнивание находится на 32-битной системе? Или, действительно, в 64-битной системе, поскольку эта структура обычно не должна быть более 32-битной. –
После того, как компиляторы поддерживают его, вы можете использовать alignas. – PlasmaHH
@JonathanLefler: Я бы предположил, что допускает автоматическую оптимизацию sse. gcc недавно добавила некоторую __builtin_assume_aligned, чтобы сообщить компилятору, что материал должен быть выровнен. Игра с примерами http://gcc.godbolt.org/ может дать больше понимания. – PlasmaHH