如何知道向量的实际最大大小?(不使用 std::vector::max_size)

Pab*_*hes 29 c++ vector

在在线课程中,我正在学习向量。在其中一个例子中,他们解释说:std::vector::max_size()应该给我向量可以达到的最大大小。我决定测试一下:

#include <iostream>
#include <exception>
#include <vector>

int main(void) {
    std::vector <int> nums;
    int max = nums.max_size();
    std::cout << "Max: " << max << std::endl;
    for (int i = 0; i < max; i++) {
        try {
            nums.push_back(i);
        }
        catch (std::bad_alloc ex) {
            std::cerr << ex.what() << std::endl;
            std::cout << "Failed at: " << i << std::endl;
            break;
        }
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这是运行它的结果:

Max: 1073741823
bad allocation
Failed at: 204324850
Run Code Online (Sandbox Code Playgroud)

它是 869416973 个整数。

所以我开始在谷歌上搜索它。在这里我读到它返回“容器可以达到的最大潜在大小”,并补充说“但绝不保证容器能够达到那个大小”。我会想象它会失败,但不会那么多。在失败之前,它只走了 1/5 的路。为什么会std::vector::max_size这样了?我认为更重要的是,有没有办法真正知道向量的潜在大小?

Som*_*ude 26

请注意,该max_size函数返回理论上的最大元素数,它没有说明所需的内存量。

如果我们假设sizeof(int) == 4(很常见)那么204324850元素将需要连续内存817299400字节(几乎 780 MiB)。

你会得到一个bad_alloc异常,因为向量根本无法分配足够的内存来保存所有元素。


eer*_*ika 22

std::vector::max_size() 应该给我向量可以达到的最大大小

这并不完全正确。max_size 为您提供了一个理论上限。Vector 绝对不会支持任何大于此大小的大小,但这并不一定意味着您可以创建所有大小不超过该大小的向量。

最大的限制因素是操作系统愿意或能够为进程分配的可用内存量。没有标准的方法来获得这个大小,甚至实现特定的方法也不是直截了当的。

另一个潜在的限制是最长的空闲连续地址空间,它可能是碎片化的。对于具有天文数字大地址空间的 64 位程序来说,这可能不是问题,但对于具有 32 位或更小地址的系统来说,这是一个考虑因素。


失败:204324850

假设 4 byte int,即大约 780 兆字节(非公制)。


结论:与其试图找出您的程序在运行时可以使用多少内存,您应该弄清楚您知道多少内存是足够的。不要分配更多。确保计算机有足够的内存,并且操作系统未配置为将内存使用限制为较少量。使用 64 位地址空间。

  • 有趣的事实:reserve() 不会弄脏它分配的内存,因此您只需要虚拟地址空间,而不是后备存储(物理 RAM + 交换空间)来实际处理它。大多数操作系统允许“过度使用”,因此如果您的系统没有足够的可用 RAM,您的程序可能会在“push_back”期间崩溃到已保留的空间。 (2认同)

Jes*_*uhl 9

这样想;在vector被写入的方式,它可以在内部处理高达(比方说)32位等值的元素,所以max_size会给你的〜2-4十亿范围的一些数字。但是你在一个只有 1MB 内存的系统上运行代码,所以当然你永远不可能把容器增长那么大。但是,vector无法知道您使用的是哪个系统 - 它只知道它的最大理论限制。


luk*_*keg 7

我会指出以下因素导致无法分配max_size内存量:

  • 您系统上的可用内存可能在max_size调用和尝试分配内存之间发生了变化
  • 可能没有足够大的连续内存块可用于分配(即总共可能有足够的内存,但被碎片化并且 vector 保证将内存存储在连续块中)
  • 当新元素添加到向量时,向量会调整大小(就像你做的那样push_back);当它发生时,旧向量的内容被复制到新向量中——并且可能没有足够的内存来同时存储它们。
  • 首先,您的系统中可能没有足够的内存。例如,在我的系统上,max_size返回类似 ( maximum_value_of_ptrdiff_t/sizeof(vector_element)) 的内容。虽然这个数字可能很大,但给定机器的物理限制可能允许更小的东西