【问题标题】:Dynamic memory addressing and deallocation动态内存寻址和释放
【发布时间】:2017-08-19 04:42:53
【问题描述】:

我正在尝试解决我正在实现动态数组的网络教程(未标记)的问题。但是,它在两个地方失败了:

  1. 我尝试在函数ResizeDynamicArray(...) 中删除动态数组
  2. 它正在输出不正确的数据。我希望看到:

    10 20 30 40 50
    10 30 40 50
    10 30 50
    

    ...但我得到了这个:

    8723216 8716480 701955994 201375930 10 
    8723216 701955994 201375930 10 
    8723216 701955994 10
    

解决方案的要求是:

  • 使用 pointer to pointer 而不是 reference to pointer(顺便说一句,我已经成功实现了 reference to pointer 解决方案,但我正在尝试找出指向指针的指针解决方案)
  • 不使用malloc/free
  • 不使用vectors
  • 必须使用如图所示的声明

有人可以建议我做错了什么吗?

int* CreateDynamicArray(int capacity, int &size);
void DeleteDynamicArray(int* dynamicArray, int &size);
void InsertElement(int* dynamicArray, int element, int &size, int &capacity);
void DeleteElement(int* dynamicArray, int elementIndex, int &size);
void ResizeDynamicArray(int** dynamicArray, int newCapacity);
void PrintArray(int *ptrArray, int capacity);

#include <iostream>

int main()
{
    int size = 0;
    int capacity = 0;

    int* ptrArray = CreateDynamicArray(capacity, size);

    InsertElement(ptrArray, 10, size, capacity);
    InsertElement(ptrArray, 20, size, capacity);
    InsertElement(ptrArray, 30, size, capacity);
    InsertElement(ptrArray, 40, size, capacity);
    InsertElement(ptrArray, 50, size, capacity);
    PrintArray(ptrArray, size);

    DeleteElement(ptrArray, 1, size);
    PrintArray(ptrArray, size);
    DeleteElement(ptrArray, 2, size);
    PrintArray(ptrArray, size);

    DeleteDynamicArray(ptrArray, size);

    ptrArray = nullptr;

    return 0;
}


int* CreateDynamicArray(int capacity, int &size)
{
    size = 0;
    return new int[capacity];
}


void DeleteDynamicArray(int* dynamicArray, int &size)
{
    if (dynamicArray != nullptr) {
        delete[] dynamicArray;
        dynamicArray = nullptr;
    }
    size = 0;
}


void InsertElement(int* dynamicArray, int element, int &size, int &capacity)
{
    if (size > capacity)
        capacity += 2;
    else
        capacity += 1;
    ResizeDynamicArray(&dynamicArray, capacity);
    dynamicArray[size] = element;
    size++;
}


void DeleteElement(int* dynamicArray, int elementIndex, int &size)
{
    for(int i = elementIndex + 1; i < size; i++)
        dynamicArray[i - 1] = dynamicArray[i];
    size--;
}


void ResizeDynamicArray(int** dynamicArray, int newCapacity)
{
    int *newArray = new int[newCapacity];
    for(int i = 0; i < newCapacity; i++) {
        newArray[i] = (*dynamicArray)[i];
    }
//  if (*dynamicArray != nullptr) {
//      delete [] *dynamicArray;
//  }
    *dynamicArray = newArray;
}


void PrintArray(int *dynamicArray, int size)
{
    for (int i = 0; i < size; i++) {
        std::cout << dynamicArray[i] << " ";
    }
    std::cout << std::endl;
}

【问题讨论】:

    标签: c++ pointers dynamic-memory-allocation pointer-to-pointer


    【解决方案1】:

    让我们看看InsertElement中的问题。你有:

    void InsertElement(int* dynamicArray, int element, int &size, int &capacity)
    {
        ...
        ResizeDynamicArray(&dynamicArray, capacity);
        ...
    }
    

    在此函数中,您可以在函数中本地修改dynamicArray 指向的内容。这不会改变调用函数中指针指向的内容。因此,您会遇到以下问题。

    1. 调用函数中的变量未指向您期望它拥有的新分配的内存。
    2. 调用函数使用它没有的内存,导致未定义的行为。
    3. 您有内存泄漏。一旦你从InsertElement返回,函数中获取的内存就会丢失给程序。

    修复它的方法是通过引用传递指针。

    void InsertElement(int*& dynamicArray, int element, int &size, int &capacity)
    {
        ...
        ResizeDynamicArray(&dynamicArray, capacity);
        ...
    }
    

    我建议将ResizeDynamicArray 更改为也接受引用指针。使用 int** 是 C 风格,而不是 C++ 风格。如果你确实改变了,你可以使用

        ResizeDynamicArray(dynamicArray, capacity);
    

    上面。

    这是我对函数声明的建议。我认为您可以相应地更新实现。

    int* CreateDynamicArray(int capacity, int &size);
    void DeleteDynamicArray(int*& dynamicArray, int &size);
    void InsertElement(int*& dynamicArray, int element, int &size, int &capacity);
    void DeleteElement(int* dynamicArray, int elementIndex, int &size);
    void ResizeDynamicArray(int*& dynamicArray, int newCapacity);
    void PrintArray(int *ptrArray, int capacity);
    

    我注意到您在 ResizeDynamicArray 中有一个错误。您正在使用:

    int *newArray = new int[newCapacity];
    for(int i = 0; i < newCapacity; i++) {
        newArray[i] = (*dynamicArray)[i];
    }
    

    将值从旧数组复制到新数组。但是,旧数组没有新数组那么多的元素。您最终会从不应该访问的内存中复制值。有必要将旧容量作为参数传递给函数,以便您可以正确复制旧值。

    【讨论】:

    • 感谢 R Sahu。我应该指出,练习的要求是使用双指针。我已经成功地在 ResizeDynamicArray 函数中使用了对指针的引用,而无需更改其他函数。
    • @Tashycat,这很不幸。这不是 C++ 的方式,但你必须做你必须做的事情。
    • 我必须承认我对为什么需要双指针方法有点困惑。但是,我更乐意学习如何使用双指针来做事。毕竟这是一个练习:-)
    • @Tashycat,如果您必须使用int**,请将我建议使用int*&amp; 的所有位置更改为int**,并相应地更新实现和用法。
    • 谢谢,R Sahu。我正在尝试自动取款机,但无法让它在不崩溃的情况下运行。我会继续努力的。
    【解决方案2】:

    我相信我有解决方案,感谢 R Sahu。

    int* CreateDynamicArray(int capacity, int &size);
    void DeleteDynamicArray(int* dynamicArray, int &size);
    void InsertElement(int** dynamicArray, int element, int &size, int &capacity);
    void DeleteElement(int** dynamicArray, int elementIndex, int &size);
    void ResizeDynamicArray(int** dynamicArray, int newCapacity);
    void PrintArray(int *ptrArray, int capacity);
    
    #include <iostream>
    
    int main()
    {
        int size = 0;
        int capacity = 0;
    
        int* ptrArray = CreateDynamicArray(capacity, size);
    
        InsertElement(&ptrArray, 10, size, capacity);
        InsertElement(&ptrArray, 20, size, capacity);
        InsertElement(&ptrArray, 30, size, capacity);
        InsertElement(&ptrArray, 40, size, capacity);
        InsertElement(&ptrArray, 50, size, capacity);
        PrintArray(ptrArray, size);
    
        DeleteElement(&ptrArray, 1, size);
        PrintArray(ptrArray, size);
        DeleteElement(&ptrArray, 2, size);
        PrintArray(ptrArray, size);
    
        DeleteDynamicArray(ptrArray, size);
    
        ptrArray = nullptr;
    
        return 0;
    }
    
    
    int* CreateDynamicArray(int capacity, int &size)
    {
        size = 0;
        return new int[capacity];
    }
    
    
    void DeleteDynamicArray(int* dynamicArray, int &size)
    {
        if (dynamicArray != nullptr) {
            delete[] dynamicArray;
            dynamicArray = nullptr;
        }
        size = 0;
    }
    
    
    void InsertElement(int** dynamicArray, int element, int &size, int &capacity)
    {
        if (size > capacity)
            capacity += 2;
        else
            capacity += 1;
        ResizeDynamicArray(dynamicArray, capacity);
        (*dynamicArray)[size] = element;
        size++;
    }
    
    
    void DeleteElement(int** dynamicArray, int elementIndex, int &size)
    {
        for (int i = elementIndex + 1; i < size; i++)
            (*dynamicArray)[i - 1] = (*dynamicArray)[i];
        size--;
    }
    
    
    void ResizeDynamicArray(int** dynamicArray, int newCapacity)
    {
        int *newArray = new int[newCapacity];
        for (int i = 0; i < newCapacity; i++) {
            newArray[i] = (*dynamicArray)[i];
        }
        if (*dynamicArray != nullptr)
            delete[] * dynamicArray;
        *dynamicArray = newArray;
    }
    
    
    void PrintArray(int *dynamicArray, int size)
    {
        for (int i = 0; i < size; i++) {
            std::cout << dynamicArray[i] << " ";
        }
        std::cout << std::endl;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-05-09
      • 2023-03-03
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-12
      相关资源
      最近更新 更多