如何模拟实现 alignas(T)?

6

我有一个数组,它被用作类型为T的对象的基础内存:

char memory[sizeof T];
.
.
.
new(memory) T(whatever);

如何确保T对象的内存对齐是正确的?在C++0x中,我可以这样写:

alignas(T) char memory[sizeof T];

但是Visual Studio 2010目前还不支持该特定功能。

4个回答

12

通常(便携式)解决方案是将内存声明与T中需要最大对齐的任何内置类型放在一个联合中。 最简单的方法是使用包含所有可能候选项的联合:

union MaxAlign
{
    int                 i     ;
    long                l     ;
    long long           ll    ;
    long double         ld    ;
    double              d     ;
    void*               p     ;
    void (*             pf)() ;
    MaxAlign*           ps    ;
} ;

union
{
    MaxAlign dummyForAlignment;
    unsigned char memory[sizeof(T)];
} rawT;

我从未听说或遇到过一台机器,无法使用上述方法。通常,只需使用double即可。(在Intel和Sparc上绝对足够。)

在极端情况下,这可能导致分配比所需更多的内存,例如如果T仅包含一个或两个char。大多数时候,这并不重要,也不值得担心,但如果需要考虑,则可以使用以下内容:

namespace MyPrivate {

template< typename T, bool isSmaller >
struct AlignTypeDetail ;

template< typename T >
struct AlignTypeDetail< T, false >
{
    typedef T type ;
} ;

template< typename T >
struct AlignTypeDetail< T, true >
{
    typedef char type ;
} ;

template< typename T, typename U >
struct AlignType
{
    typedef typename AlignTypeDetail< U, (sizeof( T ) < sizeof( U )) >::type
                        type ;
} ;
}

template< typename T >
union MaxAlignFor
{
    typename MyPrivate::AlignType< T, char >::type        c ;
    typename MyPrivate::AlignType< T, short >::type       s ;
    typename MyPrivate::AlignType< T, int >::type         i ;
    typename MyPrivate::AlignType< T, long >::type        l ;
    typename MyPrivate::AlignType< T, long long >::type   ll ;
    typename MyPrivate::AlignType< T, float >::type       f ;
    typename MyPrivate::AlignType< T, double >::type      d ;
    typename MyPrivate::AlignType< T, long double >::type ld ;
    typename MyPrivate::AlignType< T, void* >::type       pc ;
    typename MyPrivate::AlignType< T, MaxAlign* >::type   ps ;
    typename MyPrivate::AlignType< T, void (*)() >::type  pf ;
} ;

在这种情况下,MaxAlignFor<T>永远不会比T更大(并且具有足够的对齐方式,因为所需的对齐方式永远不会大于T的大小)。
请注意,标准没有正式保证这些内容。但它实际上是可行的。

@Mehrdad,它说VC++不支持某个特定功能。它并没有说这是唯一使用的编译器。 - James Kanze
@JamesKanze:抱歉,我在错误的帖子下评论了。请看下面我的帖子。 - user541686

5

在搜索 vc++ align 之后,会显示这个页面:使用 __declspec(align(#))


4
正如主导的 __ 明显表示的那样,这是一个编译器特定的扩展。 - James Kanze
1
@JamesKanze:虽然已经晚了3年,但我还是要提一下……问题中确实写着Visual C++ :) - user541686
@JamesKanze:对不起,我用手机评论时没有意识到我在错误的帖子下评论。我的回复应该是针对你在这里的评论,在这里回复。 - user541686

3
如果 T 是标准布局且 union 被良好定义,则
union
{
   T t;
   char memory[sizeof T];
};

应该对齐。


2

要么在堆上分配内存(这里有对齐保证),要么使用boost::aligned_storage


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接