9

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

class my_class { ... };

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

或者由于指针转换/对齐考虑,这是否有问题?

4

5 回答 5

15

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

虽然存在各种技巧来获得正确对齐的存储,但最好使用 Boost's 或 C++0x's 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)];
于 2011-01-03T09:10:17.403 回答
3

As people have mentioned here, this won't necessarily work due to alignment restrictions. There are several ways to get the alignment right. First, if you have a C++0x-compliant compiler, you can use the alignof operator to try to force the alignment to be correct. Second, you could dynamically-allocate the character array, since memory from operator new is guaranteed to be aligned in such a way that anything can use it correctly. Third, you could try storing the character array in a union with some type that has the maximum possible alignment on your system; I believe that this article has some info on it (though it's designed for C++03 and is certainly not as good as the alignof operator that's coming out soon).

Hope this helps!

于 2011-01-03T09:11:59.903 回答
2

由于对齐,它至少是有问题的。

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

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

于 2011-01-03T09:05:32.170 回答
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)> {};
于 2012-07-28T21:50:46.830 回答
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你使用哪种类型来获得正确的对齐。

于 2011-01-03T09:07:42.520 回答