1

我有一个轻量级模板类,其中包含几个很少使用的成员对象,因此我想避免调用它们的构造函数和析构函数,除非在我实际使用它们的极少数情况下。

为此,我在课堂上像这样“声明”它们:

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 数组是否在所有情况下都正确对齐,或者我需要采取一些额外的步骤来确保它们正确对齐?(如果是这样,一个不依赖于平台的步骤会更好)

4

7 回答 7

2

也许我不明白你的问题,但你不能这样做char *keyBuf[..size..];,最初将它设置为 NULL (未分配)并在你第一次需要它时分配它?

你试图用新的位置做的事情似乎有风险的业务和糟糕的编码风格。

无论如何,代码对齐是依赖于实现的。

于 2009-12-18T03:24:11.210 回答
2

请问您为什么要将它们放入 char 缓冲区中?为什么不直接创建 K 和 V 的指针对象,然后在需要时实例化它。

于 2009-12-18T03:25:20.470 回答
2

无法保证您会获得适当的对齐方式。数组通常只保证为成员类型对齐。对齐数组以char存储char.

一个例外是分配的数组具有char最大对齐,因此您可以将任意类型存储到其中。但是此保证不适用于您的情况,因为您要避免堆分配。unsigned charnew

TR1 和 C++0x 添加了一些非常有用的类型:

std::alignment_ofstd::aligned_storage一起给你一个便携(和功能)的答案。

std::alignment_of<T>::value为您提供 type 所需的对齐方式Tstd::aligned_storage<A, S>::type为您提供具有对齐A和大小的 POD 类型S。这意味着您可以安全地将对象写入类型为 的变量std::aligned_storage<A, S>::type

(在 TR1 中,命名空间是std::tr1,而不仅仅是std

于 2009-12-18T19:10:03.200 回答
0

如果要更改代码对齐方式,请使用 pragma pack

#pragma pack(push,x)

// class code here

#pragma pack(pop) // to restore original pack value

如果 x 为 1,则元素之间将没有填充。

这是一个阅读链接

http://www.cplusplus.com/forum/general/14659/

于 2009-12-18T03:46:03.737 回答
0

我在http://www.gamedev.net/community/forums/topic.asp?topic_id=455233找到了 SiCrane 发布的这个答案:

但是,对于静态分配,将内存块声明为与其他类型的联合会减少浪费。那么内存块将保证与联合中最严格类型的对齐方式对齐。无论哪种方式,它仍然很丑陋。

听起来工会可以解决问题!

于 2009-12-18T04:36:39.483 回答
0

我建议您查看boost::optional模板。它可以满足您的需求,即使您不能使用它,您也应该查看它的实现。

它使用alignment_ofandtype_with_alignment来进行对齐计算和保证。

于 2009-12-18T07:26:10.847 回答
-2

长话短说,这对你的表现没有任何帮助,而且会引起很多头痛,不久你就会陷入编写自己的内存管理器的过程中。

放置 new 对于 POD 来说很好(但不会为你节省任何东西),但如果你有一个构造函数,那么它根本就不会工作。

如果您使用placement new,您也不能依赖布尔变量的值。

Placement new 有用途,但不是真的。

于 2009-12-18T04:57:13.830 回答