【问题标题】: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 的一个优点是您不需要将容量传递给函数。使用数组,您将传递数组的起始地址和容量。是的,我知道其中的区别。

标签: c++ arrays c++11


【解决方案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)。这将允许某人将它与用户定义的容器一起使用。
    猜你喜欢
    • 2020-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-04-19
    • 2013-11-15
    • 1970-01-01
    • 2011-11-12
    • 1970-01-01
    相关资源
    最近更新 更多