结构体中的数组可以得到什么对齐保证?

发布于 2024-08-15 02:29:47 字数 659 浏览 4 评论 0原文

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

为此,我在类中“声明”它们,如下所示:

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 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

意中人 2024-08-22 02:29:47

无法保证您会获得适当的对齐方式。通常,数组仅保证成员类型对齐。 char 数组针对 char 的存储进行对齐。

一个例外是使用 new 分配的 charunsigned char 数组具有最大对齐方式,以便您可以在其中存储任意类型。但这种保证不适用于您的情况,因为您正在避免堆分配。

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

std::alignment_ofstd::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 of char.

The one exception is that char and unsigned char arrays allocated with new 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 and std::aligned_storage together give you a portable (and functioning) answer.

std::alignment_of<T>::value gives you the alignment required for a type T. std::aligned_storage<A, S>::type gives you a POD type with alignment A and size S. That means that you can safely write your object into a variable of type std::aligned_storage<A, S>::type.

(In TR1, the namespace is std::tr1, rather than just std)

吃兔兔 2024-08-22 02:29:47

请问为什么要将它们放入字符缓冲区中?为什么不直接创建 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.

紅太極 2024-08-22 02:29:47

也许我不明白你的问题,但你不能只做 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.

橙幽之幻 2024-08-22 02:29:47

如果您想更改代码对齐方式,请使用 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/

If you want to change code alignment use pragma pack

#pragma pack(push,x)

// class code here

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

if x is 1, there will be no padding between your elements.

Heres a link to read

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

君勿笑 2024-08-22 02:29:47

我在 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 :

However, for static allocations, it's less wasteful to declare the memory block in a union with other types. Then the memory block will be guaranteed to be aligned to the alignment of the most restrictive type in the union. It's still pretty ugly either way.

Sounds like a union might do the trick!

执着的年纪 2024-08-22 02:29:47

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

它使用 alignment_oftype_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 and type_with_alignment for its alignment calculations and guarantees.

郁金香雨 2024-08-22 02:29:47

把一个非常非常长的故事写得非常非常短,这对你的表现没有任何帮助,而且会引起很多麻烦,而且用不了多久你就会陷入编写自己的内存管理器的困境。

对于 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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文