以下合法C ++是否具有明确定义的行为?
class my_class { ... };
int main()
{
char storage[sizeof(my_class)];
new ((void *)storage) my_class();
}
或者这是因为指针转换/对齐考虑因素有问题吗?
答案 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>