将 C cstyle 数组视为 std::array

问题描述 投票:0回答:4

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

c++
4个回答
27
投票

正如本文中所讨论的 如果 T 是 POD,std::array 是否保证是 POD?

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

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

我认为保证可以按标准工作。但我必须承认,我有时在解释标准语言时遇到困难,所以如果我错了,请纠正我。

问候 克拉斯


14
投票

您可以使用 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<> 的大小不再与 C 数组的大小匹配(由于 STL 实现中的一些更改),这将产生错误。


12
投票

你不能那样做。

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


0
投票

这个问题很老了,但是由于

std::array
似乎可以保证是POD,所以
reinterpret_cast
之前的检查甚至可能没有必要。

尽管如此,还是有静态检查可以确保万无一失。有函数

is_trivial
is_standard_layout
用于在编译时检查类型是否为 POD。 (
is_pod
已弃用) 然后,也可以按照上面的建议在编译时检查
sizeof(data) == sizeof(std::array<int, size>)
。 在我的用例中,当我想要转发一些索引时,我想动态创建一个
const std::array&
而不必总是编写
g(std::array{1,8,9})
。我不知道这是否有人感兴趣,但你就可以了:

template<typename T,std::size_t size>
void g(const std::array<T,size>& a)
{
  //...
}

template<typename T,std::size_t size> 
void g(T const (&indices)[size])
{
    static_assert(std::is_standard_layout_v< std::array<T,size>>);
    static_assert(std::is_trivial_v< std::array<T,size>>);
    static_assert(sizeof(indices) == sizeof(std::array<T,size>),"std::array<T, N> isn't layout-compatible with T[N].");
    g(reinterpret_cast<const std::array<T,size>&>(indices));
}

int main()
{
    g({1,8,9});
}

神箭

© www.soinside.com 2019 - 2024. All rights reserved.