#include<iostream> using namespace std; class Point { public: Point(int a0, int b = 0); Point(const Point &p); void print() { cout<<x<<" "<<y<<endl; } private: int x, y; }; Point::Point(int a, int b) { x = a; y = b; cout<<"Using normal constructor\n"; } Point::Point(const Point &p) { x = 2 * p.x; y = 2 * p.y; cout<<"Using copy constructor\n"; } void fun1(Point p) { p.print(); } Point fun2() { Point p4(10,30); return p4; } int main() { Point p1(30,40); p1.print(); Point p2(p1); p2.print(); Point p3 = p1; p3.print(); fun1(p1); p2 = fun2(); p2.print(); return 0; }
本人不太理解输出结果最后一行 为什么会输出20 和 60
解决方案
5
打印不是很清楚么?
Point p4(10,30); //一般构造
然后返回p4拷贝构造临时变量,调用拷贝构造函数,就各乘以2了;假如开启了优化,此步可能会被优化掉。
最后临时变量拷贝赋值给p2,调用的是operator =,但你没有重载,所以没打印输出。
Point p4(10,30); //一般构造
然后返回p4拷贝构造临时变量,调用拷贝构造函数,就各乘以2了;假如开启了优化,此步可能会被优化掉。
最后临时变量拷贝赋值给p2,调用的是operator =,但你没有重载,所以没打印输出。
10
返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,假如本人创建一个临时对象用户返回,那么这个临时对象会消 耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。
你假如是VS的话:DEBUG和RELEASE模式能很清楚的看到,假如是GCC编译器,可能编译器本人进行了RVO优化,看不到区别
你假如是VS的话:DEBUG和RELEASE模式能很清楚的看到,假如是GCC编译器,可能编译器本人进行了RVO优化,看不到区别
5
p2 = fun2();//fun2中构造了(10,30)的对象,在return时调用了拷贝构造,于是成了(20,60)
5
很明显,在题主是在windows环境下运行的这段代码,假如要是使用gcc的话你会发现有多处了一个“Using normal constructor”输出,其中原因,3楼已经给出了完整的解释。
对于题主的问题。
关键是下面两条语句:
p2 = fun2();
p2.print();
执行赋值符号右侧的fun2();时
Point fun2()
{
Point p4(10,30);
return p4;
}
调用了通用构造函数构造出p4. x、y分别是10 和 30。
当执行赋值符号时,p2 = fun2();会调用拷贝构造函数。拷贝构造函数需要将x、y都乘以2,所以输出结果变成了20和60.这个拷贝构造函数的调用是由赋值符号引起的。
对于题主的问题。
关键是下面两条语句:
p2 = fun2();
p2.print();
执行赋值符号右侧的fun2();时
Point fun2()
{
Point p4(10,30);
return p4;
}
调用了通用构造函数构造出p4. x、y分别是10 和 30。
当执行赋值符号时,p2 = fun2();会调用拷贝构造函数。拷贝构造函数需要将x、y都乘以2,所以输出结果变成了20和60.这个拷贝构造函数的调用是由赋值符号引起的。