结构体中的数组可以得到什么对齐保证?
我有一个轻量级模板类,其中包含几个很少使用的成员对象,因此我想避免调用它们的构造函数和析构函数,除非在我实际使用它们的极少数情况下。
为此,我在类中“声明”它们,如下所示:
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++ FAQ 它说,当使用新的放置时,我需要小心放置是否正确对齐,否则我会遇到麻烦。
我的问题是,keyBuf 和 valBuf 数组在所有情况下都会正确对齐,还是需要采取一些额外的步骤来确保它们正确对齐? (如果是这样,最好采用不依赖于平台的步骤)
I've got a lightweight templated class that contains a couple of member objects that are very rarely used, and so I'd like to avoid calling their constructors and destructors except in the rare cases when I actually use them.
To do that, I "declare" them in my class like this:
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)];
};
... and then I use placement new and placement delete to set up and tear down the objects only when I actually need to do so.
Reading the C++ FAQ it said that when using placement new, I need to be careful that the placement is properly aligned, or I would run into trouble.
My question is, will the keyBuf and valBuf arrays be properly aligned in all cases, or is there some extra step I need to take to make sure they will be aligned properly? (if so, a non-platform-dependent step would be preferable)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
无法保证您会获得适当的对齐方式。通常,数组仅保证成员类型对齐。
char
数组针对char
的存储进行对齐。一个例外是使用
new
分配的char
和unsigned char
数组具有最大对齐方式,以便您可以在其中存储任意类型。但这种保证不适用于您的情况,因为您正在避免堆分配。TR1 和 C++0x 添加了一些非常有用的类型:
std::alignment_of
和std::aligned_storage
一起为您提供了一个可移植(且有效)的答案。std::alignment_of::value
为您提供类型T
所需的对齐方式。std::aligned_storage::type
为您提供一个具有对齐A
和大小S
的 POD 类型。这意味着您可以安全地将对象写入std::aligned_storage::type
类型的变量。(在 TR1 中,命名空间是
std::tr1
,而不仅仅是std
)There's no guarantee that you'll get the appropriate alignment. Arrays are in general only guaranteed to be aligned for the member type. A
char
array is aligned for storage ofchar
.The one exception is that
char
andunsigned char
arrays allocated withnew
are given maximum alignment, so that you can store arbitrary types into them. But this guarantee doesn't apply in your case as you're avoiding heap allocation.TR1 and C++0x add some very helpful types though:
std::alignment_of
andstd::aligned_storage
together give you a portable (and functioning) answer.std::alignment_of<T>::value
gives you the alignment required for a typeT
.std::aligned_storage<A, S>::type
gives you a POD type with alignmentA
and sizeS
. That means that you can safely write your object into a variable of typestd::aligned_storage<A, S>::type
.(In TR1, the namespace is
std::tr1
, rather than juststd
)请问为什么要将它们放入字符缓冲区中?为什么不直接创建 K 和 V 的指针对象,然后在需要时实例化它。
May I ask why you want to place them into a char buffer? Why not just create pointer objects of K and V then instantiate it when you need it.
也许我不明白你的问题,但你不能只做 char *keyBuf[..size..]; ,将其最初设置为 NULL (未分配)并第一次分配它你需要它吗?
您尝试对新的放置进行的操作似乎是有风险的业务和糟糕的编码风格。
无论如何,代码对齐取决于实现。
Maybe I didn't understand your question, but can't you just do
char *keyBuf[..size..];
, set it initially to NULL (not allocated) and allocate it the first time you need it?What you're trying to do with placement new seems risky business and bad coding style.
Anyway, code alignment is implementation dependent.
如果您想更改代码对齐方式,请使用 pragma pack(
如果 x 为 1),则元素之间不会有填充。
的链接
这是阅读http://www.cplusplus.com/forum/general/14659/
If you want to change code alignment use pragma pack
if x is 1, there will be no padding between your elements.
Heres a link to read
http://www.cplusplus.com/forum/general/14659/
我在 http://www.gamedev 上找到了 SiCrane 发布的答案。 net/community/forums/topic.asp?topic_id=455233 :
听起来工会可能会解决问题!
I found this answer posted by SiCrane at http://www.gamedev.net/community/forums/topic.asp?topic_id=455233 :
Sounds like a union might do the trick!
我建议您查看
boost::optional
模板。它可以满足您的需要,即使您无法使用它,您也应该查看它的实现。它使用
alignment_of
和type_with_alignment
进行对齐计算和保证。I recommend that you look at the
boost::optional
template. It does what you need, even if you can't use it you should probably look at its implementation.It uses
alignment_of
andtype_with_alignment
for its alignment calculations and guarantees.把一个非常非常长的故事写得非常非常短,这对你的表现没有任何帮助,而且会引起很多麻烦,而且用不了多久你就会陷入编写自己的内存管理器的困境。
对于 POD 来说,放置 new 很好(但不会为你节省任何东西),但如果你有一个构造函数,那么它根本就不起作用。
如果您使用新的放置,您也不能依赖于布尔变量的值。
新的展示位置有用途,但实际上并非如此。
To make a very very long story very very short this isn't going to help your performance any and will cause lots of headaches and it won't be long before you get sucked into writing your own memory managemer.
Placement new is fine for a POD (but won't save you anything) but if you have a constructor at all then it's not going to work at all.
You also can't depend on the value of your boolean variable if you use placement new.
Placement new has uses but not really for this.