C++ 将数组引用'T(&;)[n]`作为'std::array<;T、 n>`

C++ 将数组引用'T(&;)[n]`作为'std::array<;T、 n>`,c++,arrays,reference,C++,Arrays,Reference,假设我有一个std::array,并希望对其内容(即未公开的elems数组成员)进行数组引用 我惊讶地发现std::array::data()返回T*,而不是T(&)[n],因此似乎需要某种类型的强制转换。我可以写: std::array<int, 5> arr; int (&ref)[5] = *reinterpret_cast<int (*)[5]>(arr.data()); std::数组arr; int(&ref)[5]=*重新解释投射(arr.data

假设我有一个
std::array
,并希望对其内容(即未公开的
elems
数组成员)进行数组引用

我惊讶地发现
std::array::data()
返回
T*
,而不是
T(&)[n]
,因此似乎需要某种类型的强制转换。我可以写:

std::array<int, 5> arr;
int (&ref)[5] = *reinterpret_cast<int (*)[5]>(arr.data());
std::数组arr;
int(&ref)[5]=*重新解释投射(arr.data());

然而,这看起来很丑陋,而且可能不安全。它是合法的(定义良好的)代码吗?还有更好的方法吗?

该标准不提供
数组的底层实现,但是如果它使用
int[5]
作为底层表示,那么对于该实现,只有您的强制转换才是合法的(不可移植的)。对于任何其他基础表示,您违反了严格的别名规则,并输入了未定义的行为


<> >而不是尝试将数组作为数组返回,可以使用迭代器对来确定您感兴趣的范围,在标准库的先决条件下?

< P> C++中的数组是一个有缺陷的类型(这里我是指C样式数组,而不是<代码> STD::数组< /C> >)。这是因为数组的大小没有存储在内存中的任何位置,只有在编译时才知道。当您将数组强制转换为其他类型(通常是指针)时,数组的大小将丢失


现在您可以看到不能执行反向转换,因为编译器无法知道数组的大小,只能查看指向第一个成员的指针。正如已经建议的,您可以使用一对迭代器来代替。

我建议使用可重用的
constexpr
函数模板来隐藏这种丑陋。最常见的情况是当大小为0时,在这种情况下,右侧将是未定义的行为,尽管在特定情况下,左侧甚至不会编译(也就是说,你不能声明一个包含0个元素的数组)使用
arr.size()
而不是
5
将不会太脆弱(它是
constexpr
,因此可以用作数组大小)。不过,我不确定转换是否定义良好。元素是连续存储的(23.3.2.1p1)那么,难道不可能将别名作为数组吗?@ EcMutu只有在<代码>数组中的原始基础类型是您所投的类型——否则它是未定义的行为,它是由原始类型的错误混叠。数组。@MarkB:但是
data()
成员必须以动态数组的形式提供对该数据的访问,动态数组与常规数组具有相同的内存布局。我倾向于说,这样做几乎总是安全的(否则很可怕)。例如
data()
已在兼容的数组中为内部表示形式添加别名way@DavidRodríguez-dribeas我确实同意这一点:实际上,几乎可以肯定它是安全的,我只是指出,就语言而言,它可能是不合法的,可能有一种合法的替代方案可以解决最初的问题。