30

是否有任何安全且符合标准的方法可以将 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,我想将现有数据称为一个。

4

3 回答 3

26

正如这篇文章中所讨论的, 如果 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 )

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

问候克拉斯

于 2013-01-29T08:21:21.297 回答
12

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

于 2012-06-26T10:21:25.457 回答
12

您可以使用reinterpret_cast,但请注意,这是一个丑陋的肮脏黑客,您不应该在您的真实发布代码中做这样的事情:

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

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

如果您仍然决定使用丑陋的脏 hack,至少添加一个编译时大小检查:

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

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

于 2012-06-26T10:24:38.157 回答