将C cstyle数组视为std :: array

jco*_*der 28 c++

是否有任何安全和标准的兼容方式将C样式数组视为std :: array而不将数据复制到新的std :: array中?

这显然不能编译,但是我想要的效果(我的实际使用更复杂,但这个简短的样本应该显示我想做的事情).我想reinterpret_cast会"工作",但可能不安全?

#include <array>

int main()
{
    int data[] = {1, 2, 3, 4, 5};

    // This next line is the important one, treating an existing array as a std::array
    std::array<int, 5>& a = data;
}
Run Code Online (Sandbox Code Playgroud)

感觉它应该是可能的,因为数据应该以相同的方式存储.

编辑:要清楚我不想清除新的std :: array,我想将现有数据称为一个.

Cla*_*aas 21

正如本文所讨论的那样, 如果T是POD,则std :: array <T,S>保证为POD吗?

std::array<int, N>是POD,因此是标准布局.据我所知,标准布局要求,这意味着指向对象的指针与指向第一个成员的指针相同.由于std :: array没有私有/受保护的成员(根据http://en.cppreference.com/w/cpp/container/array),这应该与包装数组中的第一个元素一致.就像这样的东西

reinterpret_cast< std::array<int, 5>* >( &data )

在我看来,保证按标准工作.不过,我必须承认,我有时难以解释标准语言,所以如果我错了,请纠正我.

关心克拉斯

  • 我认为你是对的,但我会检查array5*p = reinterpret_cast <array5*>(&data); ASSERT(p-> data()==&data); 这是我们最终想要的 (3认同)

jua*_*nza 11

你不能这样做.它std::array是一个聚合并拥有自己的数据块(而不是指向可以轻松重新分配的数据块的指针).所以没有办法避免所有元素的副本.在C++ 11中,这一点特别重要,因为数组的数据无法移动,因此没有高效的std::swap功能.

  • 我明白那个.我不想用它自己的数据创建一个新的std :: array,我想将现有数据称为std :: array,因为它们可能是相同的布局.如果可以安全地做到这一点.我确定reinterpret_cast"hack"会"起作用"...... (7认同)

Iva*_*kov 9

您可以使用reinterpret_cast,但请注意,这是一个丑陋的脏黑客,您不应该在您的真实版本代码中执行以下操作:

std::array<int, 5> &a = reinterpret_cast<std::array<int, 5>&>(data);
Run Code Online (Sandbox Code Playgroud)

如果std :: array的内部实现发生更改(例如,将在STL的调试版本中添加一些其他字段以执行某些运行时检查),则可能会出现问题.然后这段代码将开始崩溃而没有任何信息性消息(因为它基于隐含的假设,即std :: array对象和C数组具有相同的内存布局).

如果你决定去寻找丑陋的脏黑客,至少要添加一个编译时大小检查:

    C_ASSERT(sizeof(a) == sizeof(data));
Run Code Online (Sandbox Code Playgroud)

如果std :: array <>的大小停止匹配C数组的大小(由于STL实现中的一些更改),这将产生错误.

  • 名称`reinterpret_cast`是故意丑陋的,以表明正在使用丑陋的黑客. (4认同)
  • @bames53 这种对 `reinterpret_cast` 的使用可能应该以 `static_assert(sizeof(data) == sizeof(std::array&lt;int, 5&gt;), "std::array&lt;T, N&gt; is not布局与 T[N] 兼容。");`. 这将提供一个明确的错误消息,表明问题,有效地防止未来(和奇怪的编译器)演员。 (4认同)
  • @JohnB C++指定类型`std :: complex`是与C`_Complex`类型的布局兼容,通过说"表达式`reinterpret_cast <cv T(&)[2]>(z)`之类的东西应该是格式良好的,`reinterpret_cast <cv T(&)[2]>(z)[0]`应指定z的实部,"等等.所以这种事情并非没有先例.`std :: array`不需要与原始数组布局兼容(例如,`std :: array`可能有额外的成员,在这种情况下你想要的实际上是不可能的),但是如果它恰好是布局兼容然后我会说这个代码是格式良好的,如果丑陋,而不是一个肮脏的黑客. (2认同)