char数组作为放置新的存储

时间:2011-01-03 08:47:27

标签: c++ pointers placement-new

以下合法C ++是否具有明确定义的行为?

class my_class { ... };

int main()
{
    char storage[sizeof(my_class)];
    new ((void *)storage) my_class();
}

或者这是因为指针转换/对齐考虑因素有问题吗?

5 个答案:

答案 0 :(得分:13)

是的,这有问题。您根本无法保证内存已正确对齐。

虽然存在各种技巧以获得正确对齐的存储,但最好使用Boost或C ++ 0x aligned_storage,这会隐藏这些技巧。

然后你需要:

// C++0x
typedef std::aligned_storage<sizeof(my_class),
                                alignof(my_class)>::type storage_type;

// Boost
typedef boost::aligned_storage<sizeof(my_class),
                        boost::alignment_of<my_class>::value>::type storage_type;

storage_type storage; // properly aligned
new (&storage) my_class(); // okay

请注意,在C ++ 0x中,使用属性,您可以这样做:

char storage [[align(my_class)]] [sizeof(my_class)];

答案 1 :(得分:3)

正如人们在此提到的,由于对齐限制,这不一定有效。有几种方法可以正确对齐。首先,如果您有一个符合C ++ 0x的编译器,则可以使用alignof运算符来尝试强制对齐。其次,您可以动态分配字符数组,因为来自operator new的内存保证以任何可以正确使用它的方式对齐。第三,你可以尝试将字符数组存储在一个联合中,其中某种类型在你的系统上具有最大可能的对齐;我相信this article有一些信息(虽然它是为C ++ 03设计的,但肯定不如即将推出的alignof运算符那么好。)

希望这有帮助!

答案 2 :(得分:2)

由于对齐,至少存在问题。

在大多数非英特尔架构上,代码会因错误对齐而产生“总线错误”,或者由于修复未对齐内存访问所需的处理器陷阱而导致速度极慢。

在英特尔架构上,这通常会比平常慢一点。除非涉及某些SSE操作,否则它也可能会崩溃。

答案 3 :(得分:2)

如果有人想要避免Boost或C ++ 1x,这个完整的代码在GCC和MSVC中都有效。特定于MSVC的代码基于Chromium的aligned_memory.h。它比GCC版本稍微复杂一些,因为MSVC的__declspec(align(.))只接受文字对齐值,并且这可以使用模板专门化来进行所有可能的对齐。

#ifdef _MSC_VER

template <size_t Size, size_t Align>
struct AlignedMemory;

#define DECLARE_ONE_ALIGNED_MEMORY(alignment) \
template <size_t Size> \
struct __declspec(align(alignment)) AlignedMemory<Size, alignment> { \
    char mem[Size]; \
};

DECLARE_ONE_ALIGNED_MEMORY(1)
DECLARE_ONE_ALIGNED_MEMORY(2)
DECLARE_ONE_ALIGNED_MEMORY(4)
DECLARE_ONE_ALIGNED_MEMORY(8)
DECLARE_ONE_ALIGNED_MEMORY(16)
DECLARE_ONE_ALIGNED_MEMORY(32)
DECLARE_ONE_ALIGNED_MEMORY(64)
DECLARE_ONE_ALIGNED_MEMORY(128)
DECLARE_ONE_ALIGNED_MEMORY(256)
DECLARE_ONE_ALIGNED_MEMORY(512)
DECLARE_ONE_ALIGNED_MEMORY(1024)
DECLARE_ONE_ALIGNED_MEMORY(2048)
DECLARE_ONE_ALIGNED_MEMORY(4096)

#else

template <size_t Size, size_t Align>
struct AlignedMemory {
    char mem[Size];
} __attribute__((aligned(Align)));

#endif

template <class T>
struct AlignedMemoryFor : public AlignedMemory<sizeof(T), __alignof(T)> {};

答案 4 :(得分:0)

char数组可能无法正确对齐myclass的大小。在某些体系结构上,这意味着访问速度较慢,而在其他体系结构中,则意味着崩溃。不应使用char,而应使用其对齐方式等于或大于struct的对齐类型,该类型由其任何成员的最大对齐要求给出。

#include <stdint.h>

class my_class { int x; };

int main() {
    uint32_t storage[size];
    new(storage) my_class();
}

要为一个my_class实例分配足够的内存,我认为size应该是sizeof(my_class) / sizeof(T),其中T是您用来获得正确对齐的任何类型。< / p>