获取嵌套stl容器的大小(以字节为单位)

时间:2018-08-23 17:38:37

标签: c++ stl containers sizeof

我已经知道std::vector<int>可以做到:

std::vector<int> v;
// populate v
std::size_t bytes = sizeof(std::vector<int>) + sizeof(int) * v.size();

但是,获取std::vector<std::set<std::array<int, 10>>>的字节大小的正确方法是什么?我必须递归调用所有嵌套容器的sizeof吗?示例:

std::vector<std::set<std::array<int, 10>>> v;
// populate v
std::size_t bytes = sizeof(v);

for(auto& s : v)
{
    bytes += sizeof(s);

    for(auto& a : s)
    {
        bytes += sizeof(a) + sizeof(int) * 10;
    }
}

还是在顶层容器中对std::vector<int>使用相同的方法?

2 个答案:

答案 0 :(得分:4)

没有一个标准的C ++容器公开它们分配多少内存的指标。将std::vector<T> v的已分配内存计算为sizeof(v) + v.capacity() * sizeof(T)似乎是可行的(因为std::vector<T>必须使用v.size()而不是v.capacity()来综合满足其性能约束。会是错误的)。但是,不能保证它给出正确的值。虽然我不知道有什么标准库实现,但是我可以想象实现vector<T>时使用指向第一个元素的指针,该指针前面有一个存储末尾,容量和分配器的控制块。

大多数容器使用内部节点,例如,指向std::list中的上一个和下一个节点的指针,或指向有序关联容器使用的树中的子节点的指针。由于这些节点可能包含其他控制信息,因此无法很好地估计这些节点的大小。另外,内存分配可能会在分配的块中使用某些信息,例如分配的块的大小。

估计这些数据结构中任何一个的已分配大小的唯一可能方法是使用自定义分配器,该分配器可跟踪使用的内存量。当然,使用这种方法意味着容器中的任何子对象也正确地将分配器用于其各自分配的内存。请注意,某些标准容器(例如std::array<T, N>不能正确地将分配器转发到其嵌套元素。在这种情况下,如果元素使用分配,则无法正确确定已使用的内存。

答案 1 :(得分:1)

首先,没有“简单”的方法可以计算STL中所有内容的存储空间。

尝试之后,我能想到的最好的就是编写自己的sizeof函数,该函数将针对您喜欢的一切实现,例如:

template<typename T>
size_t metaSizeOf(const T& t)
{
    return sizeof(T);
}

然后将其专门化,例如,对于向量,您将需要以下内容:

template<typename T, typename Alloc, template <typename, typename> class V>
size_t metaSizeOf(const V<T, Alloc>& v)
{
    size_t bytes = sizeof(V<T, Alloc>);
    for(const auto& t: v) bytes += metaSizeOf(t);
    return bytes;
}

并使用您拥有的所有模板接口复制/粘贴相同的代码,例如对于套:

template<typename T, typename Compare, typename Alloc, template <typename, typename, typename> class V>
size_t metaSizeOf(const V<T, Compare, Alloc>& v)
{
    size_t bytes = sizeof(V<T, Compare, Alloc>);
    for(const auto& t: v) bytes += metaSizeOf(t);
    return bytes;
}

以此类推。您还可以针对特定情况编写自己的实现。例如,对于数组,您可以编写通用函数:

template<typename T, std::size_t N, template <typename, std::size_t> class V>
size_t metaSizeOf(const V<T, N>& v)
{
    size_t bytes = sizeof(V<T, N>);
    for(const auto& t: v) bytes += metaSizeOf(t);
    return bytes;
}

但是您也可以只为阵列选择专用的优化版本:

template<typename T, std::size_t N>
size_t metaSizeOf(const std::array<T, N>&)
{
    return sizeof(std::array<T, N>) + N * sizeof(T);
}

Example @ IdeOne.com

但是,正如其他人指出的那样,您只会计算原始数据的大小,这远非准确的。 The memory usage of STL containers can be surprising.