【问题标题】:Create a big array in C++ [duplicate]在 C++ 中创建一个大数组 [重复]
【发布时间】: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]

一切都很好。

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

最好的问候,

【问题讨论】:

    标签: c++


    【解决方案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】:
      【解决方案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 可能有点为时过早。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2022-01-13
          • 2020-03-01
          • 1970-01-01
          • 1970-01-01
          • 2021-03-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多