【问题标题】:Simplest way to get memory size of std::array's underlying array?获取 std::array 底层数组内存大小的最简单方法?
【发布时间】:2017-09-27 13:04:31
【问题描述】:

这是在内存中获取std::array::data() 返回的内容大小的最简单/最短的方法吗?

arr.size() * sizeof(arr.value_type)

编辑:我的问题并不准确。 “内存中的大小”是指数组中包含的所有元素(它们本身)的大小,例如,如果它们是指向结构的指针,我只想要指针的大小,而不是指向的结构。我也不想包括std::arr 实现的任何可能开销的大小。只是数组元素。

有人建议sizeof(arr)。这:What is the sizeof std::array<char, N>? 不同意。虽然它似乎在我的机器上工作我想知道标准保证什么。

【问题讨论】:

  • 这应该是一个自我回答的问题吗?
  • 为什么不只是sizeof arr
  • 试试sizeof(arr)
  • 您要包含还是排除填充?
  • @nwp,没有 C 数组不能有填充(即 T[N] 的大小始终为 sizeof(T)*N ),标准明确表示。当然 T 本身可以有填充,一个持有 T[N] 的结构也可以...

标签: c++ sizeof stdarray


【解决方案1】:

您可以直接在您的std::array 实例上使用sizeof 运算符:

sizeof(arr)

例子:

struct foo
{
    int a;
    char b;
};

int main()
{
    std::array<foo, 10> a;
    static_assert(sizeof(foo) == 8);
    static_assert(sizeof(a) == 80);
}

live example on wandbox


来自cppreference

std::array是一个封装固定大小数组的容器。

此容器是一个聚合类型,其语义与 struct 相同,它持有 C 样式数组 T[N] 作为其唯一的非静态数据成员。

【讨论】:

  • 并保证sizeof(struct{T t[N];}) == N * sizeof(T)? (尤其是sizeof(std::array&lt;char,3&gt;) == 3?)
  • @YSC,即使是(我不这么认为),“具有相同的语义”意味着具有相同的大小(一个简单的反例是 std::array).
  • @MassimilianoJanes 虽然你的反例可能被认为是一个特例,我愿意看过去,就像我在帖子的编辑中提到的那样,显然sizeof 不是要走的路完全没有。
  • @NPS:我不明白——你想知道数组占用了多少内存,对吧?如果是这样,sizeof 是最好的选择,因为它会准确地告诉您 std::array 实例占用的内存量,即使它与 T*size 不同。
  • @NPS:如果你想知道 T*size 是什么,而不关心 std::array... 只需 sizeof(T) * N
【解决方案2】:

不能保证sizeof(std::array&lt;T,N&gt;) == N*sizeof(T),但可以保证sizeof(std::array&lt;T,N&gt;) &gt;= N*sizeof(T)。额外的大小可能是命名(但未指定)的成员和/或未命名的填充。

保证是因为被包装的T[N] 数组必须是std::array&lt;T,N&gt; 的第一个成员,但没有指定其他成员。

【讨论】:

  • std::array 是一个没有 std::initializer_list 构造函数的聚合(使用列表/聚合初始化),所以它唯一的非静态成员是 C 样式数组,意味着不应该有任何其他未指定的成员。
  • @AndyG:其他未指定的成员将被初始化为 0、nullptr 或 false,不是吗?聚合初始化不需要为所有成员提供初始化器。
  • 我想你是对的。 cppreference 的引述让我大吃一惊。 (与包含 Cstyle 数组的结构相同的语义并不意味着它实际上只包含一个 cstyle 数组,只是 cstyle 数组需要位于第一个)
【解决方案3】:

由于没有人发布比我的第一个猜测更好的内容,并且sizeof(arr) 很可能不保证不包括任何可能的额外 std::array's 字段的大小,我选择了这个作为公认的答案。

arr.size() * sizeof(arr.value_type)

如果有人提出更好的建议,我很乐意接受他们的回答。

【讨论】:

  • @Moberg 哇,这是很久以前的事了。我什至不记得为什么我当时不接受它(也许 SO 不允许立即接受,然后我忘记了?)。总之,修好了。谢谢。
  • :D(发一张开心的脸还不够,我还要写点什么)
【解决方案4】:

我知道您在问:array&lt;value_type,N&gt; arr 的元素的集合占用的内存大小是多少,即在arr.begin()arr.end() 之间?

答案是sizeof(value_type)*N,这在标准中有说明,但需要一些处理才能得出这个结论。

在 C++ 标准 [dcl.array] 中(这是关于 (c-)array 而不是 std::array):

数组类型的对象包含一个连续分配的非空集合,由 N 个类型为 T 的子对象组成。

在 [expr.add] 中(此处术语数组指的是(c-)数组):

当一个具有整数类型的表达式被添加到指针或从指针中减去时,结果具有类型 的指针操作数。如果表达式 P 指向具有 n 个元素的数组对象 x 的元素 x[i],则 86 表达式 P + J 和 J + P(其中 J 的值为 j)指向(可能是假设的)元素 x[i + j] 如果 0 ≤ i + j ≤ n;否则,行为未定义。同样,表达式 P - J 指向 (可能是假设的)元素 x[i - j] 如果 0 ≤ i - j ≤ n;否则,行为未定义。

在 [array.data] 中(这里的数组指的是std::array):

constexpr T* data() noexcept;
constexpr const T* data() const noexcept;

返回:一个指针使得 data() == addressof(front()) 和 [data(), data() + size()) 是 有效范围。

所以data() 将一个有效范围返回给std::array 的元素,该范围可以使用指向 value_type 的指针进行迭代,因此它遵循遵循 (c-) 数组索引规则的指针算法,以及(c-) 数组是连续的。 Q.E.D.

【讨论】:

  • 不,我问“获得该尺寸的最简单方法是什么。”
  • 我以为你在问这个尺寸的标准保证是否是arr.size()*sizeof(arr_type::value_type)。我不确定对您来说“最简单”是什么意思,但arr.size()*sizeof(arr_type::value_type) 是一个常量表达式:它在编译时进行评估,它不会生成任何代码。
  • 我的意思是最简单的代码,所以写/计算越少越好。
  • 0 用于执行,一些用于开发。代码越复杂,出错的可能性就越大。更简单的代码会产生更少的错误。它也更容易记住,写起来也更快。
  • @NPS 我坚持这个观点。然而,当没有更好的选择时,就没有更好的选择!
【解决方案5】:

我认为你必须恢复使用类似的辅助函数

template <typename T>
auto getSize(T& t) -> size_t {
    typename T::size_type size = t.size();
    size_t value_type_size = sizeof(typename T::value_type);

    return size * value_type_size;
}

【讨论】:

    【解决方案6】:

    阅读documentation of std::array。所以是的,它可能是。或者尝试一下

      (arr.size()-1) * sizeof(arr.value_type) + sizeof(std::array<T,1>)
    

    但我只会使用sizeof(arr)

    顺便说一句,我不确定您对此是否有任何正式保证。我猜这个标准理论上会允许std::arraystd::vector一样,除了resize()和其他一些方法会被隐藏。但是没有一个理智的实现会这样做(因为 std::array 已被发明用于将普通数组打包到类似于向量的容器中)。

    也许只允许std::array-s 最多两个元素的实现(否则抛出一些异常)可能符合标准的字母。

    【讨论】:

    • 如何在保留std::array 的聚合初始化的同时拥有与vector 相同的布局(即存储在动态分配的内存中的值)?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-09
    • 2018-09-10
    • 1970-01-01
    • 2010-11-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多