我重载了 << 和 = 运算符。为什么当我将一个对象分配给另一个对象并尝试打印它时,打印出来的是垃圾?
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 Length
的 operator=
值,所以您调用了 Length
复制构造函数。但是您的 class 没有复制构造函数,因此它使用默认值,而该默认值会做错事。发生的情况是,当您从 operator=
return 时,this->numb
指针被复制到临时对象,即 operator=
的 return 值。然后该临时对象被销毁,其结果是 this->numb
指向的内存被删除。这就是为什么你在打印时看到垃圾 x
,因为它的内部存储器已被释放。
可以进行两个修复,return 来自 operator=
的引用,并为您的 class 编写一个有效的复制构造函数。两者都可以解决问题,你应该两者都做。
您还应该阅读 rule of three,以充分理解这个非常重要的问题。
我有一个 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 Length
的 operator=
值,所以您调用了 Length
复制构造函数。但是您的 class 没有复制构造函数,因此它使用默认值,而该默认值会做错事。发生的情况是,当您从 operator=
return 时,this->numb
指针被复制到临时对象,即 operator=
的 return 值。然后该临时对象被销毁,其结果是 this->numb
指向的内存被删除。这就是为什么你在打印时看到垃圾 x
,因为它的内部存储器已被释放。
可以进行两个修复,return 来自 operator=
的引用,并为您的 class 编写一个有效的复制构造函数。两者都可以解决问题,你应该两者都做。
您还应该阅读 rule of three,以充分理解这个非常重要的问题。