删除数组或释放内存,C ++错误

时间:2015-07-25 01:02:25

标签: c++ memory-management data-structures stack dealloc

下面是我正在尝试实现的堆栈数据结构的代码片段。

由于某些原因,当我删除currentArray时,newArray也会被删除,因为下面的代码会给我一个运行时错误,其中包含newArray和{{1}的内容是垃圾值。

我不确定为什么会这样。

非常感谢有关我为什么会收到此错误的任何见解,以及下面的currentArray实施是从基本角度出发的。

push()

4 个答案:

答案 0 :(得分:2)

push功能中,在else区块中执行

currentArray = newArray;

因此,currentArraynewArray都指向同一件事! (你自己做的)。

因此,当您执行delete [] currentArray时,您无需删除newArray,因为该内存已被删除。这就是为什么你的程序发出错误,你试图删除已被删除的内存!!

此外,在您的推送功能中,您执行::

currentArray = new T[size];
currentArray = newArray;

我相信你的classcurrentArraypointer,而new也会返回指向新分配内存的指针。因此,如果您希望currentArray指向newArray,则只需执行currentArray = newArray而无需为currentArray分配内存。

此外,您还可以::

 newArray = new T[size];
 copy(currentArray, currentArray + size, newArray);

在if块中,我相信您正在将数据currentArray复制到newArray,因此,在您将数据从currentArray复制到newArray之后,您需要delete以前为currentArray分配了内存,否则是内存泄漏(程序中的故障导致丢弃内存,导致性能下降或失败)delete记忆总是好的,这是没用的。

因此,我建议您在此之后添加delete [] currentArray语句。

所以,你的最终代码看起来像这样::

// Destructor
~Stack() 
{
    /*
     *if ((size > 0) && (currentArray) != NULL) --> 
     *deleting a NULL pointer is completely defined!
     *So, in your constructor if you are initializing 
     *currentArray to NULL you need not have any if condition.
    */
    delete[] currentArray;
}

inline void push(T value)
{
    if (isEmpty())
    {
        size++;

        currentArray = new T[size];
        currentArray[size - 1] = value;
    }
    else
    {
        size++;

        newArray = new T[size];

        copy(currentArray, currentArray + size, newArray);

        delete [] currentArray; //EDIT

        newArray[size - 1] = value;

        //currentArray = new T[size]; --> Deleted Line
        currentArray = newArray;
    }
}

注意:: 如果您的编译器符合C ++ 11,您应考虑使用nullptr而不是NULL,原因如下:{{3 }}

答案 1 :(得分:2)

首先,您不需要在析构函数中进行检查。

~Stack() {
    delete [] currentArray;
    delete [] newArray;
}

推动有几个问题:

  1. 您按值传递value,这可能很昂贵。你应该通过参考传递。
  2. 在递增后,size中使用copy(),这意味着您将原始内存复制到newArray的最后一个广告位。这可能是良性的(T = int +运气)或灾难性的(T = std :: string)。
  3. 仅在newArray内需要
  4. push()。它应该是局部变量,而不是成员变量。
  5. 每次增长1,这会导致填充O( n 2 )时间。您应该以几何方式增长,这需要额外的容量成员变量。
  6. 您两次调用new T[size]。其中一个泄漏。
  7. 这是一个重新设计的版本:

    class Stack {
    public:
        …
        inline void push(const T& value) {
            if (size_ == capacity_) {
                capacity_ = capacity_ ? capacity_ * 2 : 1;
                T* dest = new T[capacity_];
                copy(data_, data_ + size_, dest);
                delete [] data_;
                data_ = dest;
            }
            data_[size_++] = value;
        }
        …
    private:
        T* data_ = nullptr;
        size_t size_ = 0, capacity_ = 0;
    };
    

    这绝不是一个坚实的,工业级的代码。它不涉及异常安全,复制避免(除其他外,需要额外的重载:push(T&& value))以及一系列其他细微之处。事实上,我甚至没有检查它编译!它可能适用于玩具项目,但在现实世界中,您应该只使用std :: stack。

答案 2 :(得分:0)

也许我错过了一些东西,但如果if陈述证明是真的,那么它无论如何都会删除。

另外,从基本的角度来看,为什么你没有:

if ((size > 0) && (currentArray != NULL) && (newArray != NULL))

这不是一个大问题,但不匹配的括号是敌人。

答案 3 :(得分:0)

@ user007这是我的pop()函数。

// Remove an element from the stack
inline const T& pop()
{
    if (size > 0)
    {
        T value;

        size--;

        value = data[size];

        T* dest = new T[size];

        // Copy the contents of the old array into the new array
        copy(data, data + (size), dest);

        delete[] data;

        data = dest;

        return value;
    }

    return NULL;
}