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

时间:2015-01-09 16:27:57

标签: c++ arrays vector

我有V = 3997962,我希望有一个这个大小的数组,包含C ++中的int向量。

当我像这样初始化它时:

const int V = 3997962;

vector<int> array[V];

程序终止而不会提示任何错误。

是否存在堆栈溢出错误?我怎么能这样做?

我应该这样定义:

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

如何将此变量传递给函数?它应该如何定义为一个论点?毕竟我需要删除它吗?

5 个答案:

答案 0 :(得分:6)

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

您可以改为使用矢量矢量。

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

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

答案 1 :(得分:6)

很可能是堆栈溢出。

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

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

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

如何将它传递给其他函数并不是真正相关的(你应该完全独立于客户端分配它们的方式来设计函数参数),但你可以只传递指针:

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

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

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

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

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

答案 2 :(得分:1)

您应该提供该阵列具有静态存储持续时间。 在某个名称空间中的任何函数外部定义它,或者如果要在函数中定义它,请使用关键字static(例如main)

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

因为堆栈内存非常有限。

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

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

或者

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

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

答案 3 :(得分:1)

矢量数据位于堆上。向量对象大小本身是(在64位,Linux上)24个字节,因此您在堆栈上找到24 * 3997962~95MB。例如,linux机器上的默认堆栈限制大约是8MB(尝试ulimit -a来检查)。所以很可能是堆栈溢出。

答案 4 :(得分:1)

如果在某些功能中将其声明为本地,则您在自动存储空间中要求3997962 * sizeof(std::vector<int>)。为了更好地了解std::vector<int>的基本管理成员占用多少空间,请考虑:

#include <iostream>
#include <vector>

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

输出(OSX 10.10,64bit clang 3.5)

24

因此,(至少在我的平台上)你要求至少 3997962 * 24,或 95951088 字节(大约 92 MB )自动存储。所以是的,你很可能会把你的自动存储空间搞得一团糟。要将单个向量的主要管理数据放在堆上,您可以:

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
}