【问题标题】:Aligning static array using std::aligned_storage使用 std::aligned_storage 对齐静态数组
【发布时间】:2013-09-09 09:37:53
【问题描述】:

我正在尝试使用 std::aligned_storage 模式实现简单静态数组的 16 字节对齐:

#include <type_traits>
int main()
{
    const size_t SIZE = 8;
    using float_16 = std::aligned_storage<sizeof(float) * SIZE, 16>::type;
    float_16 mas;
    new(&mas) float[SIZE];//Placement new. Is this necessary? 

    mas[0]=1.f;//Compile error while attempting to set elements of aligned array
}

我得到以下编译错误:

在«mas[0]»中没有匹配«operator[]»

然后我尝试使用显式指针转换:

float* mas_ = reinterpret_cast<float*>(mas); 

但这也会产生编译错误:

类型 «float_16 {aka std::aligned_storage::type}» 输入 «float*»

谁能建议我如何正确使用 std::aligned_storage 对齐静态数组?

【问题讨论】:

  • 为什么不用new返回的指针?
  • new 返回的@avakar 指针没有扩展对齐。
  • @R.MartinhoFernandes:我认为 avakar 谈论的是新的展示位置(对齐)。 (见我的回答)
  • @R.MartinhoFernandes,Jarod42 是正确的,我自然是在谈论原始问题中的新位置。

标签: c++ arrays pointers c++11 memory-alignment


【解决方案1】:

你可以使用:

float* floats = new (&mas) float[SIZE];

然后你可以使用:

floats[0] = 1.f;

根本没有reinterpret_cast :)

【讨论】:

  • 我担心使用placement new 进行数组分配,因为分配可能需要额外空间来跟踪分配大小,这是afaik 实现-定义。
  • @FabioA.:确实,为了绝对安全,我们必须循环以使 SIZE 放置新 :( 或使用 std::array&lt;float, SIZE&gt; 或类似的。
【解决方案2】:

做事

alignas(16) float mas[SIZE];

std::aligned_storage 是来自boost 的 C++03 遗物。

【讨论】:

  • @gorill 是的 4.7 不支持它。尝试将您的编译器更新到 4.8。
  • aligned_storage 不是 C++03 的遗物。它对齐原始存储,而alignas 对齐对象。这些是不同的目的。尽管在这种特殊情况下没有太大区别,aligned_storage 提供了非冗余功能。
  • @R.MartinhoFernandes 没有什么是typedefusing 无法替代的。
【解决方案3】:

mas 不是指针。 reinterpret_cast 必须只涉及指针、引用或整数类型,并且只能在某些组合中涉及:指向和来自整数类型的指针、指向指针的指针、对引用的引用或自身的整数类型。在这种情况下,您尝试将 std::aligned_storage&lt;32u, 16u&gt;::type 大小写为指针。您可以从中得到的最好的结果是对指针转换的引用,但这是不允许的†。

尝试将其地址转换为另一种指针类型:reinterpret_cast&lt;float*&gt;(&amp;mas);


† 为了好玩:如果std::aligned_storage&lt;32u, 16u&gt;::type 是指针类型,您可能会遇到最糟糕的情况。这是值得怀疑的,因为 32 字节指针并不常见,但它可能发生在 std::aligned_storage&lt;8u, 8u&gt;::type 上,例如,在一个非常讨厌的标准库中。让我们称之为地狱++。因此,在 Hell++ 中,它会编译得很好,并且您最终会将指针类型转换为另一种指针类型,然后对其进行所有讨厌的操作,例如取消引用它。这将是灾难性的,因为如果std::aligned_storage&lt;32u, 16u&gt;::type 是指针类型,则对象将没有存储地址,而是成为存储。

【讨论】:

  • 它有效,但我可以放心,mas_ 真的是 16 字节对齐的吗?
  • @gorill 如果不是,请为您的标准库实现提交错误。 (您可以通过将指针重新解释为整数并检查它是否可被 16 整除来测试它)
  • reinterpret_cast&lt;float*&amp;&gt;(mas) 会将mas 处的位模式解释为指针 - 这不是预期的。请改用reinterpret_cast&lt;float*&gt;(&amp;mas)
  • @SebastianRedl 哦,真的!他想要一个数组,而不是一个指针。哎呀。谢谢。 (现在我觉得很傻,在张贴了那条笔记并在这里造成了同样的事情之后)
  • 哦,拜托。我会直言不讳。在开始搞乱reinterpret_castaligned_storage 之前,您需要先学习一些基本的C++。
猜你喜欢
  • 1970-01-01
  • 2018-03-09
  • 2013-10-18
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
  • 2015-03-27
  • 2013-03-05
  • 1970-01-01
相关资源
最近更新 更多