我重载了 << 和 = 运算符。为什么当我将一个对象分配给另一个对象并尝试打印它时,打印出来的是垃圾?

I have overloaded << and = operators. Why when I assign an object to another and try to print it I get junk printed out?

我有一个 class Length 的程序。此 class 具有类型为 int 的名为 size 的属性和一个动态 char 类型的数组 *numb。我重载了运算符 <<= 以便我可以打印对象值并将一个对象的值分配给另一个对象。

如果我将 operator = 的 return 类型保留为 void,该程序似乎工作正常,但如果我尝试 return 一个 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
}

你应该return这里参考:

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

为了进一步说明 molbdnilo 所说的,您的代码有两个问题。第一个问题是 operator= 应该 return 参考。如果没有,这不是错误,但会导致行为与赋值的正常行为不一致。这里就不细说了,喜欢的可以自己去看看

但是当结合你的第二个错误时,你确实会遇到问题。因为您是 returning Lengthoperator= 值,所以您调用了 Length 复制构造函数。但是您的 class 没有复制构造函数,因此它使用默认值,而该默认值会做错事。发生的情况是,当您从 operator= return 时,this->numb 指针被复制到临时对象,即 operator= 的 return 值。然后该临时对象被销毁,其结果是 this->numb 指向的内存被删除。这就是为什么你在打印时看到垃圾 x,因为它的内部存储器已被释放。

可以进行两个修复,return 来自 operator= 的引用,并为您的 class 编写一个有效的复制构造函数。两者都可以解决问题,你应该两者都做。

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