C++动态数组,增加容量

Posted

技术标签:

【中文标题】C++动态数组,增加容量【英文标题】:C++ dynamic array, increasing capacity 【发布时间】:2014-06-19 15:26:40 【问题描述】:

我正在尝试实现一个动态数组,这是我增加容量的函数

int* changeCapacity(int *arr, int length, int newCapacity) 
    int *newArr = new int[newCapacity];

    if(length > newCapacity)
        return 0;
     else 
        for(int i = 0; i < length; i++)
            newArr[i] = arr[i];
        
        delete[] arr;
        arr = newArr;
        return arr;
    

这是我得到的错误:

speicher(2465,0x7fff7cfc2310) malloc: * 对象 0x7f9742403910 的错误:未分配被释放的指针 * 在 malloc_error_break 中设置断点进行调试

我这样称呼它:

int* addElement(int *arr, int& length, int& capacity, int val)
if(length >= capacity)
    capacity = capacity * 2;
    changeCapacity(arr, length, capacity);

    arr[length] = val;
    length += 1;
    return arr;
else

    arr[length] = val;
    length += 1;
    return arr;

【问题讨论】:

如果length &gt; newCapacity,你正在泄漏内存。 您正在使用 C++。使用std::vector&lt;int&gt; 会处理所有这些问题。然后你就可以早点回家了。 你能告诉我们你是如何调用这个函数的吗? 你为什么认为他是他? arr[length] 超出length 对象数组的范围,但我认为这不是问题所在。这两个函数都没有调用free(),所以我认为问题可能出在其他地方......另外,在changeCapacity() 中,我认为对于新请求的容量小于现有容量的情况返回 0 可能不是明智的设计选择... 【参考方案1】:

我认为您的问题必须来自两件事 IMO

第一

changeCapacity(arr, length, capacity);
arr[length] = val;

这里没有新的 arr 值(由 changeCapacity() 返回)。 因此,您的函数 addElement() 将返回错误的指针,并在您的下一个 addElement() 上执行释放内存损坏。

为什么要获取新的 arr 值?

你做的和这里一样

a = 1;
changeVar(a);
// value of a here?

int changeVar(int a)

   a = 5;
   return (a);

a 的价值如何? 1 因为changeVar的参数是一个局部变量。

第二:

您在 addElement() 函数上赋予 NULL 值。

【讨论】:

【参考方案2】:

现在您正在更改arr 的地址,您必须在其中通过引用传递指针。这样做:

int* changeCapacity(int *&arr, int length, int newCapacity)

【讨论】:

如果 OP 使用返回值,则不需要,因为新指针是从 changeCapacity 返回的。 这就是为什么完整的代码示例很重要。真正的问题可能是他如何使用函数,而不是函数本身。 当容量不需要增加时,OP 还必须修复返回 0。这是一个糟糕的选择。 或者使用自己的返回值 如果在参数中给出引用,为什么要返回 int*?【参考方案3】:

这在某种程度上是基于错误消息的猜测,但您已经表明:

int* addElement(int *arr, int& length, int& capacity, int val)
 //...
  changeCapacity(arr, length, capacity);
  //...

调用:

int* changeCapacity(int *arr, int length, int newCapacity)
 //...
  delete[] arr;
  //...

但是,鉴于您迄今为止发布的代码,addElement()arr 参数的原始来源未知。你是不是碰巧做了这样的事情:

foo()
 int array[N];
  //...
  addElement(array, ...);
  //...

或者使用全局数组变量调用addElement()?在任何一种情况下,原始数组都不是通过new[] 分配以匹配delete[],这似乎是运行时库所抱怨的。错误信息中指出的指针的值往往让我认为它最初是在堆栈上分配的。

当然,其他问题,例如没有捕获changeCapacity() 和/或addElement() 的返回值,以及changeCapacity() 可能返回空指针的可能性仍然有效,应该修复。

【讨论】:

【参考方案4】:

这是一种更好的方法。所有想学习的人都在 cmets 中得到了很好的解释:

        #include <iostream>
        using namespace std;

        int* changeCapacity(int *arr, int length, int newCapacity);
        int* addElement(int *arr, int& length, int& capacity, int val);

        int main()
            int length = 0; // no inital elements in array
            int capacity = 1; // initial capacity is one
            int* arr = new int[capacity]; // allocating space for values
            int* temp; // pointer for storing temporary values
            /* loop for adding elements to the array */
            for(int i=0;i<21;i++)
                temp = addElement(arr,length,capacity,i); // adding an element to the array
                if(temp == NULL)  // checks if execution was successful
                    cout<< "NULL returned...\n Exiting Now...";
                    return 0; // exits the program on failure
                
                arr = temp; // changing the value of arr
            
            /* loop for printing the array */
            for(int i=0;i<length;i++)
                cout<<arr[i]<<" ";          
            
            return 0;
        
        /* function for increasing the capacity of array */
        int* changeCapacity(int *arr, int length, int newCapacity) 
            int *newArr = new int[newCapacity]; // definging a new array

            if(length > newCapacity) // checking if the length of the array is valid
                cout<< "invalid length of array\n";
                return NULL;
             else 
                /* loop for transferring values to the new array */
                for(int i = 0; i < length; i++)
                    newArr[i] = arr[i];
                
                delete[] arr; // deleting the old array (clears the memory of the old array)
                // arr = newArr; removed as this is not needed
                return newArr; // returns the new array
            
        

        /* function for adding a new element to the array */
        int* addElement(int *arr, int& length, int& capacity, int val)
        if(length >= capacity) // checks if the array has space for storing the given value or not
            capacity = capacity * 2; // doubles the capacity of the array
            int* temp = changeCapacity(arr, length, capacity); // changes the size of the array to the new one
            if(temp == NULL) // checking if a null was returned
                cout<< "Failed to change capacity\n";
                return NULL; // returning  NULL
            
            arr = temp; // the value of arr was not changed in your code (problem corrected)
            arr[length] = val; // stores the value in the array
            length += 1; // increasing the number of element count of the array
            return arr; // returns the new array
        else
            arr[length] = val; // stores the value in the array
            length += 1; // increasing the number of element count of the array
            return arr; // returns the new array
        
        

【讨论】:

这段代码也存在内存泄漏。问题中的同样错误。 我认为最好预先为元素分配空间,而不是每次插入新元素时都为它们分配空间。这将要求您为每次插入遍历整个数组。我本可以使用链表或向量来解决这个问题,但考虑到这个问题,我认为最好保留问题的原始代码。此外,它还跟踪分配的内存。

以上是关于C++动态数组,增加容量的主要内容,如果未能解决你的问题,请参考以下文章

为啥动态数组必须以几何方式增加其容量以获得 O(1) 摊销的 push_back 时间复杂度?

C++ 动态数组每次添加都会将大小增加 1 - 错误

C++中定义动态数组

C++中定义动态数组

一个动态数组的例子C++

如何在C++中创建一维动态数组