我有一个轻量级的模板类,它包含很少使用的成员对象,所以我想避免调用它们的构造函数和析构函数,除非在我实际使用它们的极少数情况下。
要做到这一点,我会在我的课堂上“宣布”他们:
template <class K, class V> class MyClass
{
public:
MyClass() : wereConstructorsCalled(false) {/* empty */}
~MyClass() {if (wereConstructorsCalled) MyCallPlacementDestructorsFunc();}
[...]
private:
bool wereConstructorsCalled;
mutable char keyBuf[sizeof(K)];
mutable char valBuf[sizeof(V)];
};
...然后我使用placement new和placement delete来设置和拆除对象,只有在我真正需要时才这样做。
阅读C ++常见问题时,它表示在使用新版本时,我需要注意放置是否正确对齐,否则我会遇到麻烦。
我的问题是,keyBuf和valBuf数组是否会在所有情况下都正确对齐,还是需要采取一些额外的步骤来确保它们能够正确对齐? (如果是这样,非平台相关步骤将更可取)
答案 0 :(得分:2)
也许我不明白你的问题,但你不能只做char *keyBuf[..size..];
,最初将它设置为NULL(未分配)并在你第一次需要时分配它?
您尝试使用新网站时所做的事情似乎有风险的业务和糟糕的编码风格。
无论如何,代码对齐取决于实现。
答案 1 :(得分:2)
请问为什么要将它们放入char缓冲区?为什么不创建K和V的指针对象,然后在需要时实例化它。
答案 2 :(得分:2)
无法保证您获得适当的对齐方式。通常只保证数组与成员类型对齐。对齐char
数组以存储char
。
一个例外是,char
和unsigned char
分配的new
数组被赋予最大对齐,因此您可以将任意类型存储到它们中。但是这种保证不适用于您的情况,因为您正在避免堆分配。
TR1和C ++ 0x添加了一些非常有用的类型:
std::alignment_of
和std::aligned_storage
一起为您提供便携(且功能正常)的答案。
std::alignment_of<T>::value
为您提供类型T
所需的对齐方式。 std::aligned_storage<A, S>::type
为您提供了对齐A
和大小为S
的POD类型。这意味着您可以安全地将对象写入std::aligned_storage<A, S>::type
类型的变量。
(在TR1中,命名空间为std::tr1
,而不仅仅是std
)
答案 3 :(得分:0)
如果要更改代码对齐,请使用pragma pack
#pragma pack(push,x)
// class code here
#pragma pack(pop) // to restore original pack value
如果x为1,则元素之间不会有填充。
这是一个阅读链接
答案 4 :(得分:0)
我发现这个答案是由SiCrane在http://www.gamedev.net/community/forums/topic.asp?topic_id=455233发布的:
但是,对于静态分配,在与其他类型的联合中声明内存块并不浪费。然后,内存块将保证与联合中最严格类型的对齐对齐。无论如何,它仍然很难看。
听起来像联盟可能会成功!
答案 5 :(得分:0)
我建议您查看boost::optional
模板。它可以满足你的需要,即使你不能使用它,你也应该看看它的实现。
它使用alignment_of
和type_with_alignment
进行对齐计算和保证。
答案 6 :(得分:-2)
要做一个非常非常长的故事非常短,这不会对你的表现有所帮助,并且会引起很多麻烦,不久之后你就会厌倦写自己的记忆管理员。
对于POD来说,Placement new是好的(但是不会保存任何东西)但是如果你有一个构造函数那么它根本不起作用。
如果使用placement new,则也不能依赖布尔变量的值。
Placement new有用但不是真的。