如何在编译时获取数组大小?

Posted

技术标签:

【中文标题】如何在编译时获取数组大小?【英文标题】:How to get an array size at compile time? 【发布时间】:2018-03-23 16:11:36 【问题描述】:

在定义 C 样式数组或 C++11 数组时,通常需要获取一个编译时常量来表示此类数组的大小。在 C 中,使用宏来做这样的事情而不依赖于可变长度数组(因为它在 C99 中不是标准的):

#define ARRAY_SIZE 1024
int some_array[ARRAY_SIZE];

#define countof(ARRAY) (sizeof(ARRAY)/sizeof(ARRAY[0]))

在 C++ 中,是否可以定义更惯用的东西?

【问题讨论】:

为什么不直接使用std::array<int, ARRAY_SIZE>std::array::size 已经是 constexpr @CoryKramer 它不适用于 C 样式数组,仅此而已。见下文如何定义一个constexpr countof,它接受 C 风格的数组、C++11 数组和元组。 你可以迁移到std::vector:std::vector<int> some_array(ARRAY_SIZE);。然后使用some_array.size() @ThomasMatthews std::vectorstd::vectorstd::array 和 C 风格的数组是别的东西。 std::vector 的一个优点是您不需要将容量传递给函数。使用数组,您将传递数组的起始地址和容量。是的,我知道其中的区别。 【参考方案1】:

使用 C++ 的 constexpr,可以找到数组的编译时常量大小:

template<std::size_t N, class T>
constexpr std::size_t countof(T(&)[N])  return N; 

并按如下方式使用:

int some_array[1024];
static_assert(countof(some_array) == 1024, "wrong size");

struct  another_array[1];
static_assert(countof(another_array) == 1, "wrong size");

请参阅full program demo on coliru。

如果有人喜欢交替使用std::array 和C 风格的数组,可以使用SFINAE 添加countof 的定义,采用std::arrays 和std::tuples:

template<class Array, std::size_t N = std::tuple_size<Array>::value>
constexpr std::size_t countof(Array&)  return N; 

请参阅enriched program demo on coliru。

【讨论】:

【参考方案2】:

如果您的标准库与 C++17 兼容,只需使用 std::size(xyz)

如果您的标准库尚未提供该功能,您可以轻松实现自己,the constexpr-specifier is C++11。

【讨论】:

很有趣,std::size 现在是constexpr。这对现代 C++ 中经典 sizeof 运算符的使用有何影响?什么时候选择一个而不是另一个?【参考方案3】:

如果您不想引入自己的函数并且只使用 STL 来实现,那么可以使用 std::distance 检索大小:

#include <utility>
auto size = std::distance(std::begin(some_array), std::end(some_array));

自 C++17 起为constexpr

【讨论】:

这里是初学者,看来你不需要c++17,直接做constexpr size_t size = std::end(some_array) - std::begin(some_array); 你好@MarkusvonBroady,你的 C++14 解决方法很棒。如果你有 C++17,使用 std::distance 而不是运算符 - 会更好,因为它适用于更多的容器(例如 std::list)。作为更通用的解决方案,我建议using std::begin, std::end 并调用begin(some_array)end(some_array)。这将允许某人将它与用户定义的容器一起使用。

以上是关于如何在编译时获取数组大小?的主要内容,如果未能解决你的问题,请参考以下文章

TypeScript:如何在编译时声明固定大小的数组以进行类型检查

编译器如何在编译时不知道大小的情况下分配内存?

java 数组类比较编译报错问题

使用 Visual C++ 编译器 (Visual Studio 2010) 的可变数组大小出错。如何规避这个问题?

编译器对数组声明大小的评估。啥时候发生?

具有非常量变量大小的编译时数组初始化