将C cstyle数组视为std :: array

时间:2012-06-26 10:17:41

标签: 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;
}

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

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

3 个答案:

答案 0 :(得分:21)

正如本文所述 Is std::array<T, S> guaranteed to be POD if T is POD?

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

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

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

此致 克拉斯

答案 1 :(得分:10)

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

答案 2 :(得分:9)

你可以使用 reinterpret_cast ,但请注意,这是一个丑陋的黑客攻击,你不应该在你的真实发行版代码中做这样的事情:

std::array<int, 5> &a = reinterpret_cast<std::array<int, 5>&>(data);

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

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

    C_ASSERT(sizeof(a) == sizeof(data));

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