1) std::to_array 是什么?
概念与定义
在 C++20 中,std::to_array 提供一种从 C 风格数组直接转换到 std::array 的工具函数,目标是让从原始数组到固定大小容器的转换变得简单、可预测且无须手动循环拷贝。通过它,开发者可以以更安全的语义来处理数组元素的拷贝与存储。
使用场景主要是需要将已有的 C 风格数组无缝转成 std::array 的场景,这样就可以享受 std::array 的固定长度、值语义和标准容器接口带来的好处。
// 例子:将 C 风格数组转换为 std::array
#include
#include int c[4] = {1, 2, 3, 4};
auto a = std::to_array(c); // N 自动从数组大小推导
std::cout << a.size() << std::endl; // 4
函数签名与语义
该转换函数在实现上以模板形式存在,核心签名为一个对 C 风格数组的引用参数:
template< class T, std::size_t N >
constexpr std::array< T, N > to_array( T (&a)[N] );
该函数被声明为constexpr,意味着在满足条件时可以在编译期完成转换,且不会涉及堆分配等运行时开销。通过引用参数 a 获取数组的大小 N,并将这 N 个元素拷贝到一个新建的 std::array 中。
如果传入的是一个 const 数组,模板参数会相应推导为 cv 限定的类型,返回的 std::array 也会包含相同的元素限定符。例如:

const int c[3] = {5, 6, 7};
auto a = std::to_array(c); // a 的元素类型为 const int
2) 从 C 数组到 std::array 的安全转换
为何安全
使用 std::to_array,你可以在编译期确定要转换的元素个数 N,并且整个转换是“值传递”的,等价于把 C 风格数组的逐个元素拷贝进一个新的 std::array 中。因此不存在越界、悬空指针等风险。
因为转换目标是 固定长度的 std::array,其大小在编译期就确定,任何超出范围的访问都将在编译期或运行时通过现有接口得到保护。
边界与限制
要注意的是,这一函数只能用于实际的 C 风格数组,而不能直接对指针、动态长度的数组或从函数返回的指针进行同样的转换。对于下列用法,编译通常会报错:传入的不是数组类型,而是指针或运行时动态分配的内存。
int* p = new int[4];
// std::to_array(p); // 编译错误:需要的是 T (&a)[N] 这样的数组引用
如果要处理动态长度的数据,应该使用 std::span 或其他运行时数据结构来表示长度,再结合容器进行管理。
另外,to_array 的目标元素类型与原数组元素类型保持一致(包括 cv 限定符),因此不会进行隐式的类型转换。若需要类型转换,需要在调用前显式处理,例如使用 std::transform。
3) 实战示例与注意事项
简单转换示例
下面的示例演示了如何将一个整型 C 风格数组转换为 std::array,并遍历输出其元素。通过该示例可以感受到 简单、直观的 API所带来的便利。
#include
#include int main() {int c[4] = {10, 20, 30, 40};auto a = std::to_array(c);for (int v : a) {std::cout << v << ' ';}// 输出:10 20 30 40
}
与 const、指针、span 的关系
对于 const 数组,to_array 仍然可用,但结果数组的元素类型会带上 const 限定符,例如 std::array
如果你需要与动态长度数据协作,推荐使用 std::span 将数据作为一个非拥有视图来处理,再结合其他容器进行转换或管理。to_array 适合静态确定长度、需要固定大小语义的场景。
#include
#include
#include void process(std::span s) {for (int x : s) std::cout << x << ' ';
}int main() {int a[3] = {1, 2, 3};auto arr = std::to_array(a);process(arr); // arr 可以隐式转换为 std::span
}


