【问题标题】:How to dynamically allocate and deallocate a 2D array using pointers in c++?如何使用 C++ 中的指针动态分配和解除分配二维数组?
【发布时间】:2020-10-14 13:32:53
【问题描述】:

我想使用指针动态分配然后解除分配二维数组。 我的想法是创建一个指向指针数组的指针,其中每个指针都指向一个 int,这就是我想做的方式。 这些函数是 bool 类型,因为无论操作是否成功,我都想返回一个布尔值。

问题是deallocateTwoDimTable 函数不返回布尔值,所以它似乎根本不起作用。如果我不使用int** table = nullptr; 但未初始化int** table,那么我会收到错误消息(释放时),我想要释放的内存尚未初始化。

如果我将参数int **table 更改为int **&table,代码确实有效,但我猜这意味着通过引用而不是使用指针传递。我如何使它工作?非常感谢所有帮助:)

这是我的主要方法:

int main() {
    int** table = nullptr;
        
    int sizeX = 5; // rows
    int sizeY = 3; // columns
    
    bool allocationResult = allocateTwoDimTable(table, sizeX, sizeY);
    cout << endl << "allocation result: " << (allocationResult ? "true" : "false") << endl;
    
    bool deallocationResult = deallocateTwoDimTable(table, sizeX);
    cout << endl << "deallocation result: " << (deallocationResult ? "true" : "false");
}

分配函数:

bool allocateTwoDimTable(int **table, int sizeX, int sizeY) {
    if (sizeX <= 0 || sizeY <= 0) return false;

    // allocate 2D table
    table = new int*[sizeX];
    for(int i = 0; i < sizeX; i++) {
        table[i] = new int[sizeY];
    }

    cout << endl << "Table " << sizeX << " x " << sizeY << endl;
    for(int i = 0; i < sizeX; i++) {
        cout << endl;
        for(int j = 0; j < sizeY; j++) {
            cout << table[i][j] << ", ";
        }
    }

    return true;
}

释放函数:

bool deallocateTwoDimTable(int **table, int sizeX) {
    if(sizeX <= 0) return false;

    for (int k = 0; k < sizeX; k++) {
        delete[] table[k];
    }

    delete[] table;

    return true;
}

【问题讨论】:

  • 如果你在table = new int*[sizeX];这样的函数中设置table,你必须通过引用传递,否则你只会设置一个副本,函数结束后会丢失。
  • 为数组之类的东西分配内存的最佳方法是使用std::vector。在销毁向量时它们更安全,事实上,如果您自己分配内存,您还应该确保在销毁指针之前自己释放内存。你可以使用std::vector中的函数push_back。
  • 您的table 数组的元素未初始化。在为这些元素分配值之前,您可能不会尝试从其元素中读取(例如使用cout &lt;&lt; table[i][j])。
  • A complete example。此外,请阅读 cmets,了解为什么您的方法(即使您让其发挥作用)存在缺陷。
  • "但我猜这意味着通过引用而不是使用指针传递" 即使它们是通过引用传递的,它仍然会使用指针。它只是对指针的引用。

标签: c++ arrays pointers


【解决方案1】:

当你需要通过引用或指针传递时,如果有机会,最好通过引用传递。

指针可以带空参数,引用不能,使用起来更安全,除非出于某种原因,您特别需要传递空参数,我认为情况并非如此。

请注意,您在打印数组时访问的是未初始化的内存。

还请注意,尽管使用布尔标志来表示分配错误,但您的代码仍然容易受到攻击,更好的方法是使用 std::exception。

bool allocateTwoDimTable(int** &table, int sizeX, int sizeY) {
    if (sizeX <= 0 || sizeY <= 0) return false;

    // allocate 2D table
    table = new int* [sizeX];
    
    for (int i = 0; i < sizeX; i++) {
        table[i] = new int[sizeY];
    }

    cout << endl << "Table " << sizeX << " x " << sizeY << endl;
    for (int i = 0; i < sizeX; i++) {
        cout << endl;
        for (int j = 0; j < sizeY; j++) {
            table[i][j] = i + j; //initializing elements of the array
            cout << table[i][j] << ", ";
        }
    }

    return true;
}
bool deallocateTwoDimTable(int (** &table), int sizeX) {
    if (sizeX <= 0) return false;

    for (int k = 0; k < sizeX; k++) {
        delete[] table[k];
    }

    delete[] table;

    return true;
}
int main() {

    int** table = nullptr;

    const int sizeX = 5; // rows
    const int sizeY = 3; // columns

    try {    
        const bool allocationResult = allocateTwoDimTable(table, sizeX, sizeY);
        cout << endl << "allocation result: " << (allocationResult ? "true" : "false") << endl;

        const bool deallocationResult = deallocateTwoDimTable(table, sizeX);
        cout << endl << "deallocation result: " << (deallocationResult ? "true" : "false");
    }
    catch (std::exception& e)
    {
        std::cout << e.what();
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

【讨论】:

    【解决方案2】:

    您必须通过引用传递指针。否则,函数 allocateTwoDimTable 将处理原始指针值的副本。即更改副本不会影响原始指针。

    此外,参数sizeX 和sizeY 应该具有size_t 类型,因为通常int 类型可能无法指定所需的数组维度。

    函数可以这样声明

    bool allocateTwoDimTable( int ** &table, size_t sizeX, size_t sizeY);
    

    注意你创建了未初始化的数组

    table[i] = new int[sizeY]
    

    所以输出它们

    cout << table[i][j] << ", ";
    

    调用未定义的行为。

    【讨论】:

    • 感谢您的详细解答。有没有其他方法可以在没有参考的情况下处理这个问题?我提到它在使用参考时确实有效,但我想知道我是否可以用其他方式做到这一点。
    • @kabugh 在主要的 cmets 中,我链接到一个答案,该答案显示了它是如何使用指针完成的。
    • @kabugh 您可以返回指向创建的指针数组的指针,而不是 bool 类型。在这种情况下,您只需检查指针是否等于 nullptr。考虑到您将需要使用不会出现异常的运算符 new。
    【解决方案3】:

    看看这个答案https://stackoverflow.com/a/936709/9936992 他们还提到了使用单个数组来模拟两个 D 数组的可能性

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-08-06
      • 1970-01-01
      • 2015-06-10
      • 2021-02-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-28
      相关资源
      最近更新 更多