我有V = 3997962,我希望有一个这个大小的数组,包含C ++中的int向量。
当我像这样初始化它时:
const int V = 3997962;
vector<int> array[V];
程序终止而不会提示任何错误。
是否存在堆栈溢出错误?我怎么能这样做?
我应该这样定义:
vector<int>* test = new vector<int>[V];
如何将此变量传递给函数?它应该如何定义为一个论点?毕竟我需要删除它吗?
答案 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
}