新手关于拷贝构造函数的一个问题

时间:2021-07-24 11:20:08
#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 个解决方案

#1


打印不是很清楚么?
Point p4(10,30); //一般构造

然后返回p4拷贝构造临时变量,调用拷贝构造函数,就各乘以2了;如果开启了优化,此步可能会被优化掉。

最后临时变量拷贝赋值给p2,调用的是operator =,但你没有重载,所以没打印输出。

#2


也就是在debug和release选项下,因为优化原因,你的最后一次打印结果是不相同的

#3


返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消 耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。
你如果是VS的话:DEBUG和RELEASE模式能很清楚的看到,如果是GCC编译器,可能编译器自己进行了RVO优化,看不到区别

#4


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.这个拷贝构造函数的调用是由赋值符号引起的。

#1


打印不是很清楚么?
Point p4(10,30); //一般构造

然后返回p4拷贝构造临时变量,调用拷贝构造函数,就各乘以2了;如果开启了优化,此步可能会被优化掉。

最后临时变量拷贝赋值给p2,调用的是operator =,但你没有重载,所以没打印输出。

#2


也就是在debug和release选项下,因为优化原因,你的最后一次打印结果是不相同的

#3


返回值优化(Return Value Optimization,简称RVO),是这么一种优化机制:当函数需要返回一个对象的时候,如果自己创建一个临时对象用户返回,那么这个临时对象会消 耗一个构造函数(Constructor)的调用、一个复制构造函数的调用(Copy Constructor)以及一个析构函数(Destructor)的调用的代价。
你如果是VS的话:DEBUG和RELEASE模式能很清楚的看到,如果是GCC编译器,可能编译器自己进行了RVO优化,看不到区别

#4


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.这个拷贝构造函数的调用是由赋值符号引起的。