【问题标题】:I have overloaded << and = operators. Why when I assign an object to another and try to print it I get junk printed out?我重载了 << 和 = 运算符。为什么当我将一个对象分配给另一个对象并尝试打印它时,我会打印出垃圾?
【发布时间】:2020-09-25 19:02:52
【问题描述】:

我有一个带有Length 类的程序。这个类有一个名为size 类型为int 的属性和一个动态的 char 类型的数组 *numb。我重载了运算符&lt;&lt;=,这样我就可以打印对象值并将一个对象的值分配给另一个对象。

如果我将operator = 的返回类型保留为void,程序似乎可以正常工作,但如果我尝试返回Length 对象,则会打印出垃圾信息。为什么?。谢谢。

这是我的代码:

class Length
{
    int size;
    char *numb;
public:
    Length()
    {

    }
    Length(int size, char *n);
    ~Length();
    friend ostream & operator << (ostream &channel, const Length &l);
    Length operator = (const Length &x);

};


Length::Length(int size, char  *n)
{
    this->size = size;
    numb = new char[size];

    for(int i = 0; i < size; i++)
    {
        numb[i] = n[i];
    }
}

ostream & operator << (ostream &channel, const Length &l)
{
    channel << "Size " << l.size <<endl;
    for(int i = 0; i < l.size; i++)
    {
        channel << l.numb[i] << endl;
    }
    return channel; 
}

Length Length::operator =(const Length &x)
{
    
    delete [] this->numb; 
    this->size = x.size;
    this->numb = new char[this->size];
    memcpy(this->numb, x.numb, this->size);
    return *this; //If I comment that line and make return type void programm works fine
}


int main()
{
    char * ch = "Hello";
    char * cx = "Hi";

    int size = strlen(ch);
    int size_x = strlen(cx);

    Length h(size, ch);
    Length x(size_x, cx);
    cout << x; //Works fine
    cout << h <<endl; //Works fine
    x = h; 
    cout << x <<endl; //Prints junk
}

【问题讨论】:

  • 阅读“三法则”,然后添加复制构造函数。 (与那个问题有点相关:operator= 应该返回一个引用,而不是一个副本)
  • @Yksisarvinen 我得到了随机字符,比如数字等。但是如果我返回一个参考就可以了。
  • 这并没有解决问题,但您确实不需要std::endl 所做的额外内容。使用'\n' 结束一行。

标签: c++ operators overloading


【解决方案1】:

为了扩展 molbdnilo 所说的内容,您的代码存在两个问题。第一个问题是operator= 应该返回一个引用。如果没有,这不是错误,但会导致行为与分配的正常行为不一致。此处不赘述,喜欢的可以去看看。

但是当与您的第二个错误相结合时,您确实会遇到问题。因为您从operator= 中按值返回Length,所以您调用Length 复制构造函数。但是您的类没有复制构造函数,因此它使用默认值,并且该默认值会做错事。发生的情况是,当您从operator= 返回时,this-&gt;numb 指针被复制到临时对象,即operator= 的返回值。然后该临时对象被销毁,其结果是this-&gt;numb 指向的内存被删除。这就是为什么当您打印出x 时会看到垃圾,因为它的内部内存已被释放。

可能有两个修复,从operator= 返回一个引用,并为您的类编写一个有效的复制构造函数。两者都可以解决问题,您应该两者都做。

您还应该阅读rule of three,以充分了解这个非常重要的问题。

【讨论】:

  • 解释得很好。谢谢。
  • @Yksisarvinen 这是一个公平的问题,也是一个复杂的话题,因为我相信准确的答案取决于所使用的 C++ 版本。我不知道所有的细节。但我认为很明显,这就是 OP 案例中正在发生的事情,如果不是这样,他们就不会看到错误。
【解决方案2】:

你应该返回这里参考:

Length& Length::operator =(const Length &x)
{
    if (this != &x)
    {
         delete [] this->numb; 
         this->size = x.size;
         this->numb = new char[this->size];
         memcpy(this->numb, x.numb, this->size);
    }
    return *this; 
}

并添加复制构造函数:

Length(Length& len) 
{
    size = len.size;
    numb = new char[size];
    for (int i = 0; i < size; ++i)
    {
         numb[i] = len.numb[i];
    } 
}   

【讨论】:

  • @Costas96 顺便说一句,您的赋值运算符还有另一个问题。在自我分配的情况下,x = x; 会失败。您可能还想阅读copy and swap idiom,这是编写赋值运算符的普遍推荐方式
猜你喜欢
  • 1970-01-01
  • 2021-03-12
  • 2019-08-07
  • 2020-01-13
  • 1970-01-01
  • 1970-01-01
  • 2016-04-15
  • 1970-01-01
  • 2020-03-28
相关资源
最近更新 更多