C++ 当临时返回对象立即分配给另一个对象时,是否调用复制构造函数
我在理解此代码的输出结果时遇到问题,如下所示:C++ 当临时返回对象立即分配给另一个对象时,是否调用复制构造函数,c++,C++,我在理解此代码的输出结果时遇到问题,如下所示: #include<iostream> using namespace std; class three_d {float x,y,z; public: three_d(){x=y=z=0;cout<<"\n\tDefault Constructor";} three_d(float a,float b,float c){x=a;y=b;z=c;cout<<"\n\tOverloaded Cons
#include<iostream>
using namespace std;
class three_d
{float x,y,z;
public:
three_d(){x=y=z=0;cout<<"\n\tDefault Constructor";}
three_d(float a,float b,float c){x=a;y=b;z=c;cout<<"\n\tOverloaded Constructor";}
three_d(const three_d &obj){x=obj.x;y=obj.y;z=obj.z;cout<<"\n\tCopy Constructor";}
three_d operator+(three_d op2);
three_d operator=(three_d op2);
void show();
~three_d(){cout<<"\n\tDestructor Working !!";}
};
three_d three_d::operator+(three_d op2)
{
x=x+op2.x;
y=y+op2.y;
z=z+op2.z;
return *this;
}
three_d three_d::operator=(three_d op1)
{
x=op1.x;
y=op1.y;
z=op1.z;
return *this;
}
void three_d::show()
{
cout<<"\n\n\tValues are : x="<<x<<" y="<<y<<" and z="<<z<<"\n";
}
int main()
{
three_d ob1(2.1,2,2.2);
three_d ob2(1,1,1), ob3;
ob3=ob1+ob2;
ob1.show();
ob2.show();
ob3.show();
return 0;
}
因此,我的问题是:
在输出的第5行中,此复制构造函数用于什么?它是用来*这个指针的,但因为它是指针,我认为它不需要一个复制构造函数?第四行是对象op2i?
如果重载=时上述语句为真,为什么只有一个副本构造函数使用,而它也有返回值?
临时返回对象何时被销毁?
请解释输出是如何像这样排序的。
即使我将重载+更改为如下内容:
三d三d::运算符+三d op2
{三个临时工;
温度x=x+op2.x;
温度y=y+op2.y;
温度z=z+op2.z;
返回温度;
}
=的复制构造函数的输出保持不变。所有值都将更改,即,对于=,只有1个复制构造函数。然而,我认为对于op1对象,=1必须有两个复制构造函数,对于*这个对象必须有另一个。
如果我在main中使用简单赋值,比如:ob3=ob1;复制构造函数的调用是预期的两倍。
请解释。运算符+和运算符=返回对象。它们是这个的复制品。因此,对复制构造函数的调用是无效的
如果要避免调用复制构造函数,为了避免复制的成本,请更改这些函数以返回引用
three_d const& three_d::operator+(three_d op2)
{
x=x+op2.x;
y=y+op2.y;
z=z+op2.z;
return *this;
}
three_d const& three_d::operator=(three_d op1)
{
x=op1.x;
y=op1.y;
z=op1.z;
return *this;
}
附言
运算符+函数修改操作数的LHS。这是罕见的。表情
a = b + c;
你不希望b被改变。这是值得思考的
如果要以良好的方式实现这些功能,应将其更改为:
three_d three_d::operator+(three_d const& rhs) const
{
three_d r(*this);
r.x += rhs.x;
r.y += rhs.y;
r.z += rhs.z;
return r;
}
three_d& three_d::operator=(three_d const& rhs)
{
if ( this != &rhs )
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
return *this;
}
理解这句话的最好方法,我认为你应该把它看作是 ob3.操作员=ob1.操作员+ob2 四,。复制构造函数: 这是从ob2创建一个临时对象,因为您通过值调用operator+。让我们称之为临时tmp2。 5.复制构造函数: 这是从ob1创建一个临时对象,因为您是通过值从运算符+返回的。让我们调用这个临时tmp1。 6.析构函数工作!!: 当operator+完成时,临时对象tmp2被破坏。 ->这里需要注意的是:VC++和GCC编译器有趣地将从操作符+返回的临时对象tmp1通过引用传递给操作符=甚至操作符=通过valuecopy获取输入。这就是为什么在这里看不到另一个复制构造函数的原因。[这需要专家解释] 7.复制构造函数: 这是从ob3创建另一个临时变量,因为您从operator=按值返回。让我们把这最后一个临时的tmp3称为tmp3。 8.析构函数工作!!: 当操作员+结束时,tmp1被破坏。 9析构函数工作!!: 操作员+结束时,tmp3在任务结束时被销毁。 当我看到GCC编译器的结果时,如下所示: 4.复制构造函数 5.复制构造函数 6.复制构造函数 7.析构函数正在工作!! 8.析构函数正在工作!! 9.析构函数正在工作 我所做的类似分析如下: tmp2创建 tmp1创建 tmp3创建 tmp3破坏 tmp1破坏 tmp2破坏
注意:我们假设您知道使用签名定义运算符+和运算符=的真正方法。一个是使用两个常量参数的friend函数,另一个是通过引用等返回的friend函数。空白是您的朋友。为什么不在重载的运算符中添加一些打印来帮助计算流呢,您应该以换行符结束邮件,而不是以换行符开头。正如@Rsahu回答中的评论所指出的,重载+以修改其左侧参数是一个糟糕的想法通常应创建并返回与其任一操作数分开的新值。这是指针*这是一个对象。operator+不应该通过引用或其他方式修改或返回*这个值语义类型,像这样的语义类型表面上是这样的:它应该通过值返回临时值。operator=通常应该返回对*this*的非常量引用,因此可以进行进一步修改,因为这是为内置类型提供的语义。这通常是一个坏主意。您已经定义了+来改变它的左参数,因此它的行为类似于+=而不是+。正是这种代码让Java设计人员确信,最好根本不允许运算符重载。@JerryCoffin,因为没有人能编写一个做同样事情的.add方法。。。对不起,我只是觉得它能做一些你没想到的事情的论点是愚蠢的。如果您知道该语言支持运算符重载,则必须将a+b视为方法调用。这是唯一的区别。@clcto:虽然我同意,但简单的事实是:1这种过载确实是一个可怕的想法,2这确实是他们为什么不允许过载的原因。
three_d three_d::operator+(three_d const& rhs) const
{
three_d r(*this);
r.x += rhs.x;
r.y += rhs.y;
r.z += rhs.z;
return r;
}
three_d& three_d::operator=(three_d const& rhs)
{
if ( this != &rhs )
{
x = rhs.x;
y = rhs.y;
z = rhs.z;
}
return *this;
}