C++ 复制构造函数不适用于循环队列?

C++ 复制构造函数不适用于循环队列?,c++,queue,copy-constructor,C++,Queue,Copy Constructor,我试图复制一个对象,它是一个循环队列。我的入队和出队工作正常,但每当我这样做时,就会出现运行时错误 CQUEUE j = k; 输出窗口显示我的复制构造函数在所有控制路径上都是递归的?有人能帮我找出我做错了什么吗?这是我的复制构造函数,以及重载赋值运算符 CQUEUE::CQUEUE(const CQUEUE& original) { (*this) = original; } void CQUEUE::operator=(CQUEUE w) { qnode *p = w.fron

我试图复制一个对象,它是一个循环队列。我的入队和出队工作正常,但每当我这样做时,就会出现运行时错误

CQUEUE j = k;
输出窗口显示我的复制构造函数在所有控制路径上都是递归的?有人能帮我找出我做错了什么吗?这是我的复制构造函数,以及重载赋值运算符

CQUEUE::CQUEUE(const CQUEUE& original)
{
(*this) = original;
}


void CQUEUE::operator=(CQUEUE w)
{
qnode *p = w.front;
(*this).front = new qnode;
(*this).back = front;

while(p -> next != w.back)
{
  back -> num = p -> num;
  p = p -> next;
  back -> next = new qnode;
  back = back -> next;
}

back -> num = p -> num;
p = p -> next;
back -> next = new qnode;
back = back -> next;
back -> num = p -> num;

back -> next = front;
front -> prev = back;
}

将赋值运算符函数更改为,并注意自赋值

void CQUEUE::operator=(const CQUEUE& w)
{
   if (this == &w)
        return *this;

   //Paste your code
}

将赋值运算符函数更改为,并注意自赋值

void CQUEUE::operator=(const CQUEUE& w)
{
   if (this == &w)
        return *this;

   //Paste your code
}
编译器正在使这一行调用复制构造函数而不是=运算符,因为=运算符当前按值采用非常量。相反,=运算符应如下所示:

void CQUEUE::operator=(const CQUEUE& w)
然后,您的复制构造函数将调用运算符=。或者,让它更明确:

CQUEUE::CQUEUE(const CQUEUE& original)
{
    Copy(original);
}

void CQUEUE::operator=(const CQUEUE& w)
{
    Copy(w);
}

void CQUEUE::Copy(const CQUEUE& other)
{
    // All your copy code here
}
编辑:是的,你是对的,你仍然需要一个复制构造函数

编译器正在使这一行调用复制构造函数而不是=运算符,因为=运算符当前按值采用非常量。相反,=运算符应如下所示:

void CQUEUE::operator=(const CQUEUE& w)
然后,您的复制构造函数将调用运算符=。或者,让它更明确:

CQUEUE::CQUEUE(const CQUEUE& original)
{
    Copy(original);
}

void CQUEUE::operator=(const CQUEUE& w)
{
    Copy(w);
}

void CQUEUE::Copy(const CQUEUE& other)
{
    // All your copy code here
}

编辑:是的,你是对的,你仍然需要一个复制构造函数。

你在某种程度上倒着做

通常,赋值运算符比复制构造函数更复杂,因为它需要在移动到新值的基础上正确处理保留的资源

用简单的部分组成一个复杂的系统通常比创建一个全套的部分并在上面表达简单的系统更容易。在您的上下文中,这意味着从复制构造函数创建赋值运算符要容易得多

因此,只需完整地编写复制构造函数:

CQUEUE(CQUEUE const& c) { ... }
然后编写一个例程来交换两个
CQUEUE
实例的内容:

void swap(CQUEUE& c) {
    using std::swap;
    swap(front, c.front);
    swap(back, c.back);
}
最后,用它们构建赋值运算符:

CQUEUE& operator=(CQUEUE c) { // copy
    this->swap(c);
    return *this;
}
这个成语被称为复制和交换(是的,非常有创意!)


注意:值得注意的是,如果你有一个移动构造器,那么它将成为一个免费的移动和交换

通常,赋值运算符比复制构造函数更复杂,因为它需要在移动到新值的基础上正确处理保留的资源

用简单的部分组成一个复杂的系统通常比创建一个全套的部分并在上面表达简单的系统更容易。在您的上下文中,这意味着从复制构造函数创建赋值运算符要容易得多

因此,只需完整地编写复制构造函数:

CQUEUE(CQUEUE const& c) { ... }
然后编写一个例程来交换两个
CQUEUE
实例的内容:

void swap(CQUEUE& c) {
    using std::swap;
    swap(front, c.front);
    swap(back, c.back);
}
最后,用它们构建赋值运算符:

CQUEUE& operator=(CQUEUE c) { // copy
    this->swap(c);
    return *this;
}
这个成语被称为复制和交换(是的,非常有创意!)


注意:额外注意,如果你有一个移动构造器,那么它将成为一个免费的移动和交换。

那太棒了,但我不必自己做,因为我试图在我自己创建的对象上使用=吗?哦,是的,你是对的。你还需要一份副本。真正的问题是操作员的签名=。我认为显式的Copy()函数可以让它更清晰。那太棒了,但是我不需要自己做,因为我试图在我自己创建的对象上使用=吗?哦,是的,你是对的。你还需要一份副本。真正的问题是操作员的签名=。我认为显式的Copy()函数可以让它更清晰。虽然正确,但这种构造重载赋值运算符的方法会在自赋值场景中强制进行不必要的复制。@契丹:问题是,自赋值如此频繁,值得为它牺牲一些可维护性吗?@Mattheiu,我们不知道分配这些物品的成本。所以我假设它们是昂贵的(比如在嵌入式系统中)来指出这一点。另外,解决方案非常优雅:)@Chethan:我不是在挑战任务的成本,而是自我任务本身的频率。我经常在这里或那里看到它被提及,但因为我从未在我所处理的任何应用程序的概要报告中看到过它,就我而言,这是一个典型的过早优化。@Kobor42:这不是它的工作方式,但是你可以请主持人将这两个问题合并在一起。虽然正确,这种制作重载赋值运算符的方法会在自赋值场景中强制进行不必要的复制。@契丹:问题是,自赋值如此频繁,是否值得牺牲一些可维护性?@Mattheiu,我们不知道分配此类对象的成本。所以我假设它们是昂贵的(比如在嵌入式系统中)来指出这一点。另外,解决方案非常优雅:)@Chethan:我不是在挑战任务的成本,而是自我任务本身的频率。我经常在这里和那里看到它被提及,但因为我从未在我所处理的任何应用程序的概要报告中看到过它,所以我认为这是一个典型的过早优化。@Kobor42:这不是它的工作方式,但是你可以请版主将这两个问题合并在一起。