通过构造函数为 vector 预分配 C++ 内存失败

标签 c++ c++11 stl

我使用的是 VS2013 (Win7 64)。我发现了一些奇怪的行为。当我使用 reserve 方法保留内存时,代码有效,但是当我通过构造函数保留时,它会抛出 bad_alloc

const int elemNumber = 100000000;
try
{
    //std::vector<int>* intVector = new std::vector<int>(elemNumber); // throws bad_alloc
    std::vector<int>* intVector = new std::vector<int>();
    intVector->reserve(elemNumber); //OK

    std::chrono::time_point<std::chrono::system_clock> start, end;
    start = std::chrono::system_clock::now();

    for (int i = 0; i < elemNumber; ++i)
    {
        intVector->push_back(i);
    }

    end = std::chrono::system_clock::now();
    std::chrono::duration<double> elapsed_seconds = end - start;
    std::cout << "Time interval: " << elapsed_seconds.count() << endl;
    delete intVector;
    cout << "Done" << endl;
}
catch (bad_alloc exc)
{
    cout << exc.what() << endl;
}

可能是什么原因?

最佳答案

hlt 已经在评论中回答了这个问题......

The constructor doesn't reserve, it resizes. Is it possible you just run out of memory?

...所以将解释发布为社区 wiki...

这...

std::vector<int>* intVector = new std::vector<int>(elemNumber); // throws bad_alloc

...需要用默认构造的元素填充 vector ,因此它正在写入 elemNumber int 所需的所有内存页面,以及初始 size()elemNumber,而...

std::vector<int>* intVector = new std::vector<int>();
intVector->reserve(elemNumber); //OK

...只是为内存保留虚拟地址——在稍后添加元素之前,操作系统不需要找到实际的后备内存;初始的 size() 仍然是 0

程序然后转到 push_back 很多元素 - 对于第一种情况,它们是除了已经在 vector 中的那些默认构造的元素,这就是内存不足的原因。

还请记住,在调整大小期间暂时使用的内存(由 push_back 超出 capacity 引起)随着容器变大而增加,容器趋向于增加的数量也会增加填充容量,这样它就不必太快再次调整大小,并且所需的任何内存在虚拟地址空间中必须是连续的(这对于 32 位应用程序来说主要是一个潜在的问题)。

关于通过构造函数为 vector 预分配 C++ 内存失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31585343/

相关文章:

c++ - 将 rand_r 更改为 srand/rand

c++ - 在使用 unique_ptr 的函数调用中使用大括号初始化的自动类型推导失败

c++ - 当它们应用于构造函数时,括号初始值设定项列表中是否有序列点?

使用接口(interface)的 C++ 命令行操作抽象

c++ - 关于根据 move 赋值和 move 构造函数实现 std::swap

c++ - std::map::upper_bound 与 std::upper_bound 性能

c++ - wifstream 中的 seekg 和 imbue 工作错误

c++ - 静态数据成员和全局变量的区别

c# - UuidCreate 是否使用 CSPRNG?

c++ - 如何在 C++ 中重复访问数组和 vector 的元素?