程序终止于大数组的初始化
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指针指向一个数组。 const
s 也可以添加到你想要不变性的地方。但是,我们可以通过完全避免使用 new
和原始指针来找到更好的解决方案。
相反,我建议使用 vector<vector<int>>
:
vector<vector<int>> test(V);
现在你实际上只有一个 vector
在堆栈上。 vector
的元素本身就是 vector
s,它们的元素也会分配到堆上。
而矢量数据位于堆上。矢量对象大小本身是(在 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
}
我有 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指针指向一个数组。 const
s 也可以添加到你想要不变性的地方。但是,我们可以通过完全避免使用 new
和原始指针来找到更好的解决方案。
相反,我建议使用 vector<vector<int>>
:
vector<vector<int>> test(V);
现在你实际上只有一个 vector
在堆栈上。 vector
的元素本身就是 vector
s,它们的元素也会分配到堆上。
而矢量数据位于堆上。矢量对象大小本身是(在 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
}