我正在进行某种中缀到后缀的转换。
我的程序工作正常,但最后它会出现某种错误!
我猜这个错误发生在以下类
的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
答案 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
作为缓冲区,它可以管理它的生命周期。