11

sizeof(std::array<char, N>)C++ 标准对应该是什么(对于某些常量N)有什么看法?

对另一个问题的评论中,有人提到std::array并不总是“分配堆栈”。该评论是对另一条评论的回应,该评论推测将太大的常量std::array声明为局部变量可能会导致程序由于“堆栈分配”变量的资源不足而中止。我认为后续评论意味着有可能std::array以某种方式切换到动态分配模式。

我可以想象,可能有某种 SFINAE 可以应用于一个数组大小阈值,它触发一个std::array实际动态分配数组并管理它的专门化。在这种情况下,sizeof(std::array<...>)可能只是指针的大小。这允许发生吗?

4

1 回答 1

20

显然sizeof(std::array<char, N>) != N如果N == 0. 它也不一定适用于N > 0。§23.3.2.1 [array.overview]/p1-2:

标头<array>定义了一个类模板,用于存储固定大小的对象序列。数组支持随机访问迭代器。array<T, N>存储N类型元素的实例T,因此这 size() == N是一个不变量。数组的元素是连续存储的,这意味着 ifa是 an array<T, N>then 它服从&a[n] == &a[0] + nall的标识0 <= n < N

数组是可以使用语法初始化的聚合(8.5.1)

array<T, N> a = { initializer-list };

whereinitializer-list是一个逗号分隔的列表,最多可N 包含其类型可转换为的元素T

§8.5.1 [dcl.init.aggr]/p1:

聚合是一个数组或一个类(第 9 条),没有用户提供的构造函数(12.1),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3) )。

由于array是聚合类型,它不能具有执行动态分配的自定义构造函数,并且它必须直接存储元素,因为它必须能够使用聚合初始化从初始值设定项列表进行初始化。但是,只要在初始化列表最多包含成员array<T, N> a = { initializer-list };时具有定义的语义,标准中的任何内容都不会阻止实现在其 C 样式数组成员之后添加额外的东西。一个看起来像的实现N

template<typename T, size_t N>
struct array {
    //typedefs and member functions omitted

    T _Elems[N];
    double _Because_I_can;
};
// specialization for N == 0 case omitted

是完全合法的。因此,不能保证sizeof(std::array<char, N>) == N.

于 2014-08-07T03:15:48.697 回答