堆栈/队列 C++ 中的内存泄漏



我有一个使用列表编写堆栈类和使用两个堆栈编写队列类的任务。我已经完成了任务,但是运行valgrind时,我发现以下代码中有内存泄漏:

T Stack<T>::pop()
{
    T *n = new T;
    *n = myStack.front();
    myStack.pop_front();
    return *n;
}

返回指针后我无法删除指针,因此我不确定如何修复它。提前谢谢。

为什么你甚至需要使用new?您可以像这样复制堆栈的最高值:

T Stack<T>::pop()
{
    T n = myStack.front();
    myStack.pop_front();
    return n;
}

所以没有分配,也没有泄漏;

复制,然后清除内存(如果pop_front内有的话)。

    T Stack<T>::pop()
    {
        T ret = myStack.front();
        myStack.pop_front();        
        return ret;
    }

你应该使用

T n = myStack.front();

在你的位置上,我会停止使用原始指针并更改为shared_ptr。是更安全。

你有多个答案给出了正确的代码,但你现有的代码是错误的原因是这样的:

T Stack<T>::pop()
{
    T *n = new T;          // allocates dynamic memory
    *n = myStack.front();  // reference to T from front() copied to allocated T object
    myStack.pop_front();   // removes the T in the stack
    return *n;  // copies your allocated T object to the return value
    // your pointer variable goes out of scope, that address is stored nowhere,
    // this is where the leak occurs...
} 
T

*n = 新 T;您正在使用新的而不是使用它来创建 T。这就是问题所在。

复制语义是C++的最大优势之一,因为你可以把编译器和类型"T"的作者归咎于:

T Stack<T>::pop() // may throw
{
    T ret = myStack.front();
    myStack.pop_front();
    return ret;
}

请注意,这是流行函数的次理想形式。复制时,可能会引发异常,这使得实现异常安全弹出函数基本上是不可能的。

容器std::stack<>通过将返回类型设为void来解决:

void Stack<T>::pop() // no-throw [if T is written by a sane coder]
{        
    myStack.pop_front();
}
T Stack<T>::back() // may throw
{        
    return myStack.front();
}

这为您提供了一种在销毁时清理堆栈而不引发异常的方法(按照惯例(而不是标准),禁止在C++中抛出析构函数)。

最新更新