【问题标题】:Dynamic Arrays动态数组
【发布时间】:2010-09-18 22:44:37
【问题描述】:

我刚刚开始学习 C++,所以请原谅这个简单的问题。我正在做的是从文件中读取数字,然后尝试将它们添加到数组中。我的问题是如何增加数组的大小?例如,我认为也许可以这样做:

#include <iostream>
using namespace std;

int main() {
    double *x;
    x = new double[1];
    x[0]=5;
    x = new double[1];
    x[1]=6;
    cout << x[0] << "," << x[1] << endl;
    return 0;
}

但这显然只是覆盖了我最初设置为 x[0] 的值 5,因此输出 0,6。我将如何使它输出 5,6?

请注意,对于我所包含的示例,我不想将它与从文件中读取的代码或要获取的代码混淆来自用户的号码。在实际应用程序中,我不知道编译时需要多大的数组,所以请不要告诉我只用两个元素创建一个数组并将它们分别设置为 5 和 6。

感谢您的帮助。

【问题讨论】:

    标签: c++ arrays


    【解决方案1】:

    您不想直接使用数组。考虑改用vector。然后,你可以调用push_back函数在末尾添加东西,它会自动为你调整向量的大小。

    #include <iostream>
    #include <vector>
    
    int
    main() {
        double value;
        std::vector<double> values;
    
        // Read in values
        while (std::cin >> value) {
            values.push_back(value);
        }
    
        // Print them back out
        for (std::size_t i(0), len(values.size()); i != len; ++i) {
            std::cout << values[i];
        }
    }
    

    【讨论】:

    • 你必须小心使用vector,它们的使用速度往往很慢。
    • 慢是相对的。即,分析您的程序并查看它是否会影响事情。如果是这样,请编写一个自定义分配器,优化分配双精度(以及大小为sizeof (double) 的对象)。
    • 它不会比通过新建、删除和复制来调整自己的大小慢。
    • @Chris Jester-Young 确实如此,而且我警告说我已经分析了很多东西,请注意我并不是说向量不好 ;-)
    • 在进行自定义分配器之前,如果您大致知道数组可能有多大,您可以使用 vector::reserve() 来确保有足够的空间来避免多次调整大小:参见例如stackoverflow.com/q/6525650/91808
    【解决方案2】:

    您应该使用集合类来为您执行此操作,而不是自己管理它。看看“矢量”类。它本质上是一个动态数组,可以根据需要自动调整大小。

    在您的情况下,您可以将“vector”与“double”类型一起使用。您可能还需要阅读 C++ 中的模板。

    http://www.cplusplus.com/reference/stl/vector/

    【讨论】:

      【解决方案3】:

      或者,如果您不想使用 STL 或其他动态的东西,您可以从头开始创建具有正确大小的数组:x = new double[2];

      当然,问题是做多大。如果你不知道,那么你只需要创建它“足够大”(比如一百或一千)......在某些时候,它不够大,它会在某些时候失败随意的样子。所以你需要调整它的大小。一旦达到这一点,您会希望从一开始就使用 STL,就像其他答案告诉您的那样。

      #include <iostream>
      using namespace std;
      int main() {
          double *x = new double[2];
          x[0]=5;
          x[1]=6;
          cout << x[0] << "," << x[1] << endl;
          return 0;
      }
      

      【讨论】:

        【解决方案4】:

        这是一个很好的例子,所以你可以看到模式:

        #include <iostream>
        using namespace std;
        
        int main() {
            // Allocate some memory for a double array of size 1 and store
            // an address to the beginning of the memory in mem_address.
            double* mem_address = new double[1];
        
            // Assign 5 to the first element in the array.
            mem_address[0] = 5;
        
            // Save the address of the memory mem_address is currently
            // referencing.
            double* saved_address = mem_address;
        
            // Allocate some memory for a double array of size 2 and store
            // an address to the beginning of the memory in mem_address.
            mem_address = new double[2];
        
            // Copy over the 1 element from the first memory block
            // to the new one.
            mem_address[0] = saved_address[0];
        
            // Done with the old memory, so clean it up.
            delete [] saved_address;
        
            // Assign 6 to the second element in the new array.
            mem_address[1] = 6;
        
            // Print out the 2 elements in the new array.
            cout << mem_address[0] << "\n";
            cout << mem_address[1] << "\n";
        
            // Done with the new array memory now, so clean it up.
            delete [] mem_address;
        }
        

        【讨论】:

          【解决方案5】:

          如果由于某种原因您无法访问 STL - 或者想自己学习如何执行此操作 - 您可以使用如下算法:

          将您的数组分配为任意大小,并记住其中有多少元素以及它有多大:

          int *a = malloc(int * ARBITRARY_SIZE);
          int size = 0;
          int allocated = ARBITRARY_SIZE;
          

          每次添加新元素时,增加“大小”。如果 size 等于 ARBITRARY_SIZE,将 'allocated' 乘以 2,然后重新分配数组。无论哪种方式,将新值分配给 a[size]。

          void addElement(int value) {
            ++size;
          
            if (size == allocated) {
              allocated *= 2;
              a = realloc(sizeof(int) * allocated);
              a = new_a;
            }
          
            a[size] = value;
          }
          

          请注意,您上面的代码至少有一个错误——在任何一种情况下,您都没有为 x[1] 分配足够的空间。

          显然,在实际代码中,您会检查 malloc 和 realloc 的返回值是否不为空。

          【讨论】:

          • 检查 malloc 的返回值是否为空也是传统的做法。与 new 不同,它不会在失败时抛出 std::bad_alloc,并且核心转储比失败的断言更难调试;-)
          • 进行了更改。虽然核心转储比大多数其他错误更容易调试:)
          【解决方案6】:

          数组总是需要一块连续的内存。在您稍后可能需要调整数组大小的情况下,重新分配可能是唯一的解决方案。这就是上面 Moish 和 Shadow2531 所做的。

          重新分配的问题在于它可能是一项昂贵的操作。因此,如果您需要向 5000 个元素的数组添加 5 个以上的元素,您最终可能会跨内存复制所有 5000 个元素。

          在这种情况下可以考虑使用链表。

          【讨论】:

            猜你喜欢
            • 2019-02-06
            • 1970-01-01
            • 2012-11-15
            • 1970-01-01
            • 1970-01-01
            • 2021-07-18
            • 2019-08-07
            • 2014-06-03
            • 1970-01-01
            相关资源
            最近更新 更多