关于return范围类对象的,对于构造函数调用的疑问。

Lqh958564333 2018-04-09 11:28:11
最近在学习C++的构造函数,遇到了一个疑问,先上一段代码
class point
{
private:
int x, y;//数据成员
public:
point(int xx = 0, int yy = 0)//构造函数
{
x = xx;
y = yy;
cout << "构造函数被调用" << endl;
}
point(point &p);//拷贝构造函数,参数是对象的引用
~point() { cout << "析构函数被调用" << endl; }
int get_x() { return x; }//方法
int get_y() { return y; }
};
point::point(point &p)
{
x = p.x;//将对象p的变相赋值给当前成员变量。
y = p.y;
cout << "拷贝构造函数被调用" << endl;
}
point g()//返回类型是point
{
point a(7, 33);
return a;
}
以上代码是为了研究类对象创建和撤销时候调用函数的情况。
void main()
{
point a=g();
}
运行结果是:
构造函数被调用
拷贝构造函数被调用
析构函数被调用
析构函数被调用
若主函数改为
void main()
{
point a(15, 22);
a=g();
}
运行结果是:
构造函数被调用
构造函数被调用
拷贝构造函数被调用
析构函数被调用
析构函数被调用
析构函数被调用
第二个主函数中,我理解是return函数返回参数副本,所以用了拷贝构造函数,所以我觉得第一个主函数应该有两个拷贝构造函数,一个是函数体内return返回参数副本调用,还有一个是外部声明定义用到拷贝构造函数,但是实际运行结果跟我想的不一样,不知道为什么
...全文
349 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lqh958564333 2018-04-10
  • 打赏
  • 举报
回复
引用 1 楼 轻箬笠的回复:
难道楼主的理解是函数的返回值会先生成一个副本,然后副本再做赋值的操作?如果是那样的话,不就多了一步开销?! 百度找了个答案。 函数返回值相当于这个函数的输出结果,如果有变量接收,就会保存到接收变量中,如你的b=f()后,结果就存到了b中。如果没有变量接收,这个返回值就被忽略了。
我也认为是多一步开销。但是我就解释不了第二个主函数里对拷贝构造函数的调用了
Lqh958564333 2018-04-10
  • 打赏
  • 举报
回复
引用 2 楼 真相重于对错的回复:
第二个主函数中,我理解是return函数返回参数副本,所以用了拷贝构造函数,所以我觉得第一个主函数应该有两个拷贝构造函数,一个是函数体内return返回参数副本调用,还有一个是外部声明定义用到拷贝构造函数,但是实际运行结果跟我想的不一样,不知道为什么 ======================= 你的理解是错的 第二个主函数里面,调用的不是拷贝构造函数,构造函数是对象初始化时候调用的,第二个函数调用的是赋值函数(operator=,你没有提供)
嗯,主函数里面是调用的赋值,但是运行结果里面有一个拷贝构造函数的调用。我的意思是这个拷贝函数的调用是由于return导致的,我是这个意思
真相重于对错 2018-04-10
  • 打赏
  • 举报
回复
第二个主函数中,我理解是return函数返回参数副本,所以用了拷贝构造函数,所以我觉得第一个主函数应该有两个拷贝构造函数,一个是函数体内return返回参数副本调用,还有一个是外部声明定义用到拷贝构造函数,但是实际运行结果跟我想的不一样,不知道为什么 ======================= 你的理解是错的 第二个主函数里面,调用的不是拷贝构造函数,构造函数是对象初始化时候调用的,第二个函数调用的是赋值函数(operator=,你没有提供)
轻箬笠 2018-04-10
  • 打赏
  • 举报
回复
难道楼主的理解是函数的返回值会先生成一个副本,然后副本再做赋值的操作?如果是那样的话,不就多了一步开销?! 百度找了个答案。 函数返回值相当于这个函数的输出结果,如果有变量接收,就会保存到接收变量中,如你的b=f()后,结果就存到了b中。如果没有变量接收,这个返回值就被忽略了。
Lqh958564333 2018-04-10
  • 打赏
  • 举报
回复
引用 5 楼 a34140974的回复:
main_1#: 1,g()内部先调用构造函数; 2,return时返回一个副本,拷贝构造; 3,gc()函数退出,销栈,析构; 4,main退出,销栈,析构; main_2#: 1,point a(15, 22)构造函数; 2,g()内部先调用构造函数; 3,return时返回一个副本,拷贝构造; 4,gc()函数退出,销栈,析构; 5,把返回的临时对象赋值给a,赋值构造; 6,临时对象,析构; 7,main退出,析构 貌似某些编译器能在某些情况下优化返回,使得调用者直接拿到g()中尾return对象的栈信息,从而避免临时变量。 个人拙见,求大神。。
嗯,我跟你理解差不多。只是我觉得第一个main里面不是return调用的拷贝构造函数,我觉得是主函数里声明定义类对象的时候用类对象对其初始化时调用的拷贝构造函数。所以我觉得可能像你说的一样,在第一个main里面return被优化了,没有产生临时变量
Lqh958564333 2018-04-10
  • 打赏
  • 举报
回复
引用 8 楼 Lqh958564333的回复:
[quote=引用 5 楼 a34140974的回复:]main_1#: 1,g()内部先调用构造函数; 2,return时返回一个副本,拷贝构造; 3,gc()函数退出,销栈,析构; 4,main退出,销栈,析构; main_2#: 1,point a(15, 22)构造函数; 2,g()内部先调用构造函数; 3,return时返回一个副本,拷贝构造; 4,gc()函数退出,销栈,析构; 5,把返回的临时对象赋值给a,赋值构造; 6,临时对象,析构; 7,main退出,析构 貌似某些编译器能在某些情况下优化返回,使得调用者直接拿到g()中尾return对象的栈信息,从而避免临时变量。 个人拙见,求大神。。
嗯,我跟你理解差不多。只是我觉得第一个main里面不是return调用的拷贝构造函数,我觉得是主函数里声明定义类对象的时候用类对象对其初始化时调用的拷贝构造函数。所以我觉得可能像你说的一样,在第一个main里面return被优化了,没有产生临时变量[/quote] 另外想请教一下关于销栈的知识,希望答友能分享一个链接
Lqh958564333 2018-04-10
  • 打赏
  • 举报
回复
引用 6 楼 小熊之怒的回复:
为什么你那样的写法会出现拷贝构造函数。
拷贝构造函数不应该是这样的吗
嗯.这个我在csdn上看到一些大神说过拷贝构造函数调用。一种就是你写的,还有一种就是在创建对象同时用类对象初始化会调用拷贝构造函数,就是我写的这个。
小熊之怒 2018-04-10
  • 打赏
  • 举报
回复
为什么你那样的写法会出现拷贝构造函数。
拷贝构造函数不应该是这样的吗
月凉西厢 2018-04-10
  • 打赏
  • 举报
回复
main_1#: 1,g()内部先调用构造函数; 2,return时返回一个副本,拷贝构造; 3,gc()函数退出,销栈,析构; 4,main退出,销栈,析构; main_2#: 1,point a(15, 22)构造函数; 2,g()内部先调用构造函数; 3,return时返回一个副本,拷贝构造; 4,gc()函数退出,销栈,析构; 5,把返回的临时对象赋值给a,赋值构造; 6,临时对象,析构; 7,main退出,析构 貌似某些编译器能在某些情况下优化返回,使得调用者直接拿到g()中尾return对象的栈信息,从而避免临时变量。 个人拙见,求大神。。

64,635

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧