【问题标题】:Copy Constructor not working for Circular Queue?复制构造函数不适用于循环队列?
【发布时间】:2012-07-10 05:36:11
【问题描述】:

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

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;
}

【问题讨论】:

    标签: c++ queue copy-constructor


    【解决方案1】:
    (*this) = original;
    

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

    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
    }
    

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

    【讨论】:

    • 那太棒了,但我不必自己制作,因为我试图在我自己创建的对象上使用 = 吗?
    • 哦,是的,你是对的。你仍然需要一个副本c'tor。真正的问题是您的运营商 = 的签名。我认为明确的 Copy() 函数使其更清晰。
    【解决方案2】:

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

    void CQUEUE::operator=(const CQUEUE& w)
    {
       if (this == &w)
            return *this;
    
       //Paste your code
    }
    

    【讨论】:

      【解决方案3】:

      你做的有点倒退。

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

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

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

      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-and-swap(是的,非常有创意!)。

      注意:额外注意,如果你有一个移动构造函数,那么它就变成了一个免费的移动和交换。

      【讨论】:

      • 虽然是正确的,但这种制作重载赋值运算符的方法会在自赋值场景中强制进行不必要的复制。
      • @Chethan:问题是,自我分配如此频繁以至于值得牺牲一些可维护性吗?
      • @Mattheiu,我们不知道分配此类对象的成本。所以我认为它们的成本很高(例如,在嵌入式系统中)来指出这一点。否则,解决方案非常优雅:)
      • @Chethan:我挑战的不是任务成本,而是自我分配的频率。我经常看到这里和那里提到它,但由于我从未见过它出现在我从事的任何应用程序的配置文件报告中,就我而言,这是一个典型的过早优化
      • @Kobor42:这不是它的工作原理,但是您可以要求版主将两个问题合并在一起。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-02
      • 1970-01-01
      • 2016-04-17
      相关资源
      最近更新 更多