程序终止于大数组的初始化

Program terminates in initialization of large array

我有 V = 3997962,我想要一个由 C++ 中的整数向量组成的那个大小的数组。

当我这样初始化它时:

const int V = 3997962;

vector<int> array[V];

程序终止,没有提示任何错误。

是不是栈溢出错误?我该怎么做?

我应该这样定义吗:

vector<int>* test = new vector<int>[V];

如何将此变量传递给函数?以及如何将其定义为参数?毕竟我需要删除它吗?

您应该提供数组具有静态存储持续时间。 要么在任何函数之外以某个名称 space 定义它,要么使用关键字 static 如果你想在函数中定义它(例如 main)

static std::vector<int> array[V];

因为堆栈内存非常有限

否则在堆中定义它或使用相同的向量。例如

std::vector<vector<int>> array( V );

std::vector<vector<int>> array;
array.reserve( V );

考虑到 class std::vector 的成员函数 max_size 允许获取有关向量的最大可接受大小的信息。

如果这是一个局部变量,你基本上是在自动存储中要求将近800万个指针变量。这可能会由于堆栈溢出而失败。

您可以改用向量的向量。

vector<vector<int>> array(V);

以上结果生成了一个名为 array 的向量,其中填充了 V 默认初始化的 vector<int>s。

很有可能是栈溢出

您正在分配 V vector<int>。虽然这些向量的元素将分配在堆上,但向量本身(包含一个指针和一些其他对象)正在堆栈上分配。如果您有 V 个,您可能会达到筹码上限。

vector<int>* test = new vector<int>[V];

这是一种可能的解决方案,但并不理想。它将要求您稍后使用 delete[] test; delete[] 数组。您 可以 通过将这个动态分配的数组包装在更智能的指针中来解决这个问题,但请继续阅读以获得更好的解决方案。

如何将其传递给其他函数并不重要(您应该设计完全独立于客户端如何分配它们的函数参数),但您可以传递指针:

void f(vector<int>* param);
f(test);

参数也可以写成vector<int> param[],这样更能表达this指针指向一个数组。 consts 也可以添加到你想要不变性的地方。但是,我们可以通过完全避免使用 new 和原始指针来找到更好的解决方案。

相反,我建议使用 vector<vector<int>>:

vector<vector<int>> test(V);

现在你实际上只有一个 vector 在堆栈上。 vector 的元素本身就是 vectors,它们的元素也会分配到堆上。

而矢量数据位于堆上。矢量对象大小本身是(在 64 位上,Linux)24 字节,所以你在堆栈上定位 24*3997962 ~ 95MB。例如,linux 机器上的默认堆栈限制为 ~8MB(尝试 ulimit -a 进行检查)。所以很可能是堆栈溢出。

你要求 3997962 * sizeof(std::vector<int>) 在自动存储 space 中,如果它被声明为局部函数。为了更好地了解 space 个 std::vector<int> 的基本管理成员占据多少,请考虑:

#include <iostream>
#include <vector>

int main()
{
    std::cout << sizeof(std::vector<int>) << '\n';
}

输出(OSX 10.10,64 位 clang 3.5)

24

因此,(至少在我的平台上)您要求 至少 3997962 * 24,或 95951088 字节(大约 92 MB) 自动存储。所以是的,您很可能会耗尽自动存储 space。要将单个向量的主要管理数据以外的所有数据放在堆上,您可以:

std::vector<std::vector<int>> vv(N);

这将创建一个包含 N 个向量的向量 int,所有这些向量最初都是空的并且由堆管理。基本向量 vv 内部的核心管理数据仍在自动存储中,但如您所见:

#include <iostream>
#include <vector>

int main()
{
    std::cout << sizeof(std::vector<std::vector<int>>) << '\n';
}

输出

24

自动存储的占用空间显着减少

解决您的后续问题:

  • 如何将此变量传递给函数?
  • 作为参数应该如何定义?

如何传递这个(第一个问题)完全取决于你是否需要修改它的内容,并且会影响你如何声明参数(第二个问题)。为避免昂贵的副本,请通过引用传递它。其次,如果被调用者不需要修改数据,则将其作为const:

传递
// read-only, pass as const-reference
void doesnt_modify(const std::vector<std::vector<int>>& vv)
{
    // use here, can't modify
}

// writable, pass as reference
void can_modify(std::vector<std::vector<int>>& vv)
{
    // use here, can modify
}