在 C++ 中创建一个大数组 [重复]

Posted

技术标签:

【中文标题】在 C++ 中创建一个大数组 [重复]【英文标题】:Create a big array in C++ [duplicate] 【发布时间】:2011-03-09 10:22:38 【问题描述】:

可能重复:Segmentation fault on large array sizes

大家好

我正在尝试使用 C++ 在 VS 2010 中创建一个非常大的数组。

当我尝试创建如下所示的数组时

int dp[4501][4501]
or
int dp[1000][1000]

它抛出了一个异常“堆栈溢出” 然后我把它改成:

int dp[100][100]

一切都很好。

那么如果我想创建一个像上面这样的大数组,我应该怎么做呢?

最好的问候,

【问题讨论】:

【参考方案1】:

使用动态分配或 STL。最近有一个关于一个非常相似的问题的帖子。见this。

【讨论】:

【参考方案2】:

把它放在theheap。

【讨论】:

除非不直接使用newmalloc 它们并没有明显的问题,尤其是在理解目标的层面上。 它们并没有明显的错误,但是“new int[4501][4501]”是错误的,这就是 GMan 的意思。 使用手动内存管理是不好的编程,把它包起来。 std::vector 就是为此目的而存在的。【参考方案3】:

你应该使用动态分配:

typedef std::vector<int> int_vector;
int_vector dp(10000);

可以通过嵌套数组来模拟双精度数组:

typedef std::vector<int_vector> int_double_vector;
int_double_vector dp(4501, int_vector(4501));

【讨论】:

我不喜欢 typedef 这样使用。为什么?很简单:您的int_array 实际上是一个int vector,而您的int_double_array 与一个double 毫无关系。 (另外,我必须进行 两次 查找才能找出它实际上是什么。) 糟糕的风格,恕我直言。仅将 typedef 用于非常复杂或神秘的事物,即使这样,也仅当它们的声明在您的代码中频繁出现时。 (我会想到成对向量映射的迭代器或函数指针。)对于只使用了两三次的声明,它们是一种混淆工具。 @Dev:我认为你对它的阅读方式太过分了。 :) 快乐的? Double 的意思是二,只是巧合的是双精度浮点类型称为 double,不要让它妨碍英语定义。代码是为人类服务的。 int_double_vector 的措辞真的很烂。你应该像 2d_int_vector 那样做某事。除了 typedef 没有问题之外,它比使用 std::vector<:vector> >::iterator... 要好得多 "double" 在编程上下文中通常(并且在“编程中的类型”上下文中几乎完全)表示“双精度浮点”。 @ypnos:经过 10 年的 C++ 维护编码,我实际上更喜欢没有 typedef 的代码。是的,这包括std::vector&lt; std::vector&lt; int &gt; &gt;::const_iterator 和类似的东西。根据我的经验,有用的 typedef 与混淆的 typedef 的比率约为 20 分之一。【参考方案4】:

如果您想避免使用new[],或避免使用std::vector,请将数组设为全局。这会将数组放在堆上,不会发生堆栈溢出。

【讨论】:

请不要使用全局变量。在这种情况下,有无数更好的解决方案(vector 不是唯一的容器类)。 @Philipp:全局变量在某些情况下很有用。而且,如果您将全局变量放入命名空间(或在结构或类中创建静态全局成员),那么它们绝对没有问题。另一种解决方案是将变量(在函数内声明)设为静态。 全局变量通常会导致比它们解决的问题更多的问题。如果您想要的只是堆分配,它们绝对不是解决方案。 我猜 OP 正在尝试解决一些编程问题,其中获得“正确”就是一切。对于只愿意让他/她的解决方案“正确”的人来说,像专业程序员一样编码是过度的。此外,使用容器代替普通数组将需要更多时间来解决问题。一旦我遇到这样的问题。我使用了 std::vector 并超出了时间限制。我只是用普通数组替换了向量并通过了我的解决方案。 -1 用于提供“不良做法”解决方案。【参考方案5】:

来自 Parashift 常见问题的文本:Why should I use container classes rather than simple arrays?

编辑:

看看***线程:

When would you use an array rather than a vector/string? Why use iterators instead of array indices?

【讨论】:

【参考方案6】:

您的堆栈溢出了太多位。你必须把它们排干。最好放在一堆其他位上。我建议 /F67108864。 /F 代表“F'ing hell 为什么堆栈与堆相比如此之小?”。 67108863 是任意的。

【讨论】:

我们需要标签来回答问题。像 funny-but-wrong-approach 这样的标签 我认为设置一个足够大的堆栈大小来处理数组是一个好方法。编译器的斜杠 /F 选项就是这样做的。在答案中添加幽默并不会使其无效并使其成为错误的方法。【参考方案7】:

您的声明看起来有点像dp 将用作矩阵。在这种情况下,专用(密集)矩阵类(如boost::numeric::ublas::matrix)是最简单的解决方案,比向量向量更容易且更局部。如果矩阵是稀疏填充的,请改用稀疏矩阵类。

【讨论】:

【参考方案8】:

所以如果我想创建一个大数组 像上面一样,我该怎么办?

避免在这些情况下使用堆栈(换句话说,避免在函数内部工作时创建类似这些不是堆分配的数组)。只是给你一个想法,我的线程本地堆栈只有 16 KB 大。 4501 * 4501 * 4(假设每个 int 4 个字节)= ~81 MB。

请考虑这样的事情:

typedef vector<int> Row;
typedef vector<Row> Matrix;
Matrix dp(4501, Row(4501) );

如果你想创建一个 10x50 矩阵:

Matrix dp(10, Row(50) );

您可以像使用普通 dp 数组一样使用它,但它不会溢出堆栈。这一个将被分配并自动释放到堆中/从堆中释放,因此您在使用时不必担心堆栈溢出。

dp[5][10] = 123;

祝你好运!

[编辑] boost 中也有矩阵解决方案值得研究,但考虑到主题的性质,建议 boost 可能有点为时过早。

【讨论】:

以上是关于在 C++ 中创建一个大数组 [重复]的主要内容,如果未能解决你的问题,请参考以下文章

为啥我们不能在c中创建一个带有常量的数组[重复]

如何在 C++ 中创建 OpenOffice 文档 [重复]

如何使用 C++ 在 %appdata% 中创建文件 [重复]

在 C++、QT 中创建 setup.exe [重复]

如何在 C++ 中创建重复直到循环?

如何在 c++ 中创建一个适用于 Windows 和 linux 的文件夹(目录)[重复]