如何使用 C++ 中的指针动态分配和解除分配二维数组?

Posted

技术标签:

【中文标题】如何使用 C++ 中的指针动态分配和解除分配二维数组?【英文标题】:How to dynamically allocate and deallocate a 2D array using pointers in 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,了解为什么您的方法(即使您让其发挥作用)存在缺陷。 "但我猜这意味着通过引用而不是使用指针传递" 即使它们是通过引用传递的,它仍然会使用指针。它只是对指针的引用。 【参考方案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 将处理原始指针值的副本。即更改副本不会影响原始指针。

此外,参数sizeXsizeY 应该具有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://***.com/a/936709/9936992 他们还提到了使用单个数组来模拟两个 D 数组的可能性

【讨论】:

以上是关于如何使用 C++ 中的指针动态分配和解除分配二维数组?的主要内容,如果未能解决你的问题,请参考以下文章

C 和 C++:释放已分配指针的一部分

指向动态二维字符数组的三重指针的内存分配

如何在 C++ 中正确使用动态分配的多维数组 [重复]

C++建立动态二维数组

C++:使用迭代器构造一个二维动态分配的数组

C++:使用函数为二维数组分配内存时出错