"双重免费或腐败" C ++中的错误

时间:2014-01-14 17:35:18

标签: c++ memory

我正在进行某种中缀到后缀的转换。

我的程序工作正常,但最后它会出现某种错误!

Error Info

我猜这个错误发生在以下类

void printQueueContents(Queue typeInfo)方法上
template <class T>
class Queue{
private:
    int front, rear, max;
    T *q;
public:
    Queue(int size=0){
        front = rear = 0;
        max = size;
        q = new T[size];
    }
    ~Queue(){
        delete []q;
    }
    int enqueue(T);
    T dequeue();

    T getValueFromIndex(int index){
        return q[index];
    }

    void printQueueContents(Queue typeInfo){
        for(int i=rear; i<front;i++){
            if(typeInfo.getValueFromIndex(i)) {
            cout<<q[i]<<" ";
            } else {
                cout<<static_cast<char>(q[i])<<" ";
            }
        }
        cout<<"\n";
    }
};

被称为:

q1.printQueueContents(q2);

并声明为:

Queue<int> q1(200);
Queue<int> q2(200); // Holds data type information for q1

我无法弄清楚为什么会这样?有什么建议?

编辑:感谢各界人士的回答。我终于设法通过将方法更改为:

来解决它
void printQueueContents(Queue& typeInfo)

这样在调用此函数时,默认的复制构造函数不会复制,析构函数也不会意外地删除相同的内存位置两次。这是一个直观解释的链接。 http://www.drdobbs.com/c-made-easier-the-rule-of-three/184401400

2 个答案:

答案 0 :(得分:2)

虽然您确实声明了析构函数,但您应该声明复制赋值运算符和复制构造函数(rule of three)。你可能不想让它们公开。

调用按值获取类的函数将调用复制构造函数。如果你没有声明任何它,你依赖于编译器生成的复制构造函数,并且它成为成员赋值的成员。在您的情况下,q*将被复制到您的第二个对象。从函数返回时,通过值传递的参数超出范围并被破坏,这将首次删除q。当你的程序退出时,原始对象的析构函数也会被调用,所以q会被第二次删除。

在您的情况下,我认为printQueueContents方法应该将const &(或ref)带到您的Queue,而不是(可能)避免昂贵的Queue对象副本。同样可以说getValueFromIndex应返回const &或ref以避免复制。对于int这不是问题,但对于课程来说,它可能会很快变得昂贵。

话虽如此,你仍然需要实现拷贝赋值运算符和拷贝构造函数,或者将它们声明为私有。

答案 1 :(得分:1)

您必须实现复制构造函数和复制赋值运算符

Queue(const Queue& rop){
 // copy rop to this, means allocate local q buffer, and copy contents of rop.q to it
}

Queue& operator=(const Queue& rop){
 // update this with rop, means the same as above
 return *this;
}

你的类必须服从rule of three,主要是因为你的类使用裸指针来分配缓冲区。您也可以使用shared_ptr作为缓冲区,它可以管理它的生命周期。