请问,这里怎么不执行copy构造函数?

goodchan 2006-04-26 11:30:03
#include <iostream>

class A
{
public:
A() { std::cout << "A::A()\n"; }
A(const A&) { std::cout << "A::A(const A&)\n"; }
~A() { std::cout << "A::~A()\n"; }
};

A f(A a)
{
std::cout << "&a" << &a << std::endl;
return a;
}

int main(int argc, char *argv[])
{
A x;

A b = f(x); // 这里不执行复制构造函数?
std::cout << "&b = " << &b << std::endl;

return 0;
}

------------------------------------------------

运行结果:

A::A()
A::A(const A&)
&a0012FF60
A::A(const A&)
A::~A()
&b = 0012FF6E
A::~A()
A::~A()
------------------------------------------------

A b = f(x);

照道理,传入 x 时执行一次,return 时执行一次,初始化 b 又执行一次,应该是三次才对啊?

可是它初始化 b 的时候不执行了。

是不是用临时的 object 来初始化就不会执行的?
...全文
375 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
lvfanqie_0 2006-04-27
  • 打赏
  • 举报
回复
第一次调用拷贝构造函数是将x赋值给a
第二次调用拷贝构造函数是将a赋值给b
由于a是临时变量,所以返回main函数的同时把a析构了
believefym 2006-04-26
  • 打赏
  • 举报
回复
return a不会调用拷贝构造函数,初始化b的时候调用了,所以还是三次
sixsavage 2006-04-26
  • 打赏
  • 举报
回复
你的copy constructor运行了两次没有错啊
传递参数的时候一次,返回的时候一次
goodchan 2006-04-26
  • 打赏
  • 举报
回复
回复人:netting_fish(好学生) ( 一级(初级)) 信誉:100 2006-04-26 21:49:00 得分:0

那么
A b;
A a=b;
是会调用拷贝构造函数的,这是为什么呢?
---------------------------------------------------

因为它是单纯的两个对象之间的初始化,而 A b = f(x); 是函数返回一个对象来初始化。当函数返回一个对象时,编译器会做一个 NRV (Named Return Value) 优化。

这是我刚刚看了 C++ primer 第三版中文版 14.8 章后知道的。
netting_fish 2006-04-26
  • 打赏
  • 举报
回复
那么
A b;
A a=b;
是会调用拷贝构造函数的,这是为什么呢?
goodchan 2006-04-26
  • 打赏
  • 举报
回复
回复人:houdy(致力于图像/图形领域,成为有思想的程序员) ( 三级(初级)) 信誉:96 2006-04-26 18:42:00 得分:0

<<<< A b = f(x); // 这里不执行复制构造函数?
>>>>
x的构造调用x的构造函数一次.
局部变量a的构造时调用x的拷贝构造一次。
在函数返回时,编译器做了优化(比较有名的优化,有个专门的名称NVR optimization),b的构造调用a的构造函数一次。
x,a,和b分别退出作用域,分别调用各自的析够函数,所以析够函数被调用三次.
---------------------------------------------------

也就是说,return a; 的时候是不用调用复制构造函数的,因为它被优化掉了。只有初始化 b 的时候用了一次?

那二楼的 believefym(暮色,miss,迷失,miss。。。) 的说法正确了。
houdy 2006-04-26
  • 打赏
  • 举报
回复
<<<< A b = f(x); // 这里不执行复制构造函数?
>>>>
x的构造调用x的构造函数一次.
局部变量a的构造时调用x的拷贝构造一次。
在函数返回时,编译器做了优化(比较有名的优化,有个专门的名称NVR optimization),b的构造调用a的构造函数一次。
x,a,和b分别退出作用域,分别调用各自的析够函数,所以析够函数被调用三次.
goodchan 2006-04-26
  • 打赏
  • 举报
回复
回复人:qynum123() ( 一级(初级)) 信誉:100 2006-04-26 17:43:00 得分:0

A b = f(x);//给b赋值的时候怎么会调用拷贝构造函数呢?是调用operator =!!!
以下语句引自"C++Primer"
一个类对象向该类的另一个对象的赋值可通过拷贝赋值操作符来执行

---------------------------------------------------

A b = xxx;

这是初始化吧? b 是一个全新的对象啊,它还没产生出来呢,怎么赋值?
goodchan 2006-04-26
  • 打赏
  • 举报
回复
又或者是 return a; 这个时候不用执行复制构造函数,只是初始化 b 执行了一次。
qynum123 2006-04-26
  • 打赏
  • 举报
回复
A b = f(x);//给b赋值的时候怎么会调用拷贝构造函数呢?是调用operator =!!!
以下语句引自"C++Primer"
一个类对象向该类的另一个对象的赋值可通过拷贝赋值操作符来执行
goodchan 2006-04-26
  • 打赏
  • 举报
回复
回复人:sankt(黄景天) ( 五级(中级)) 信誉:110 2006-04-26 17:20:00 得分:0

int main(int argc, char *argv[])
{
A x;

A b = f(x); // 这里传入x的时候会调用拷贝构造函数来创建一个临时对象.没有显示,是因为被编译器优化掉了

std::cout << "&b = " << &b << std::endl;

return 0;
}

---------------------------------------------------

没有优化掉,它已经显示出来了。

A::A() --------> x 诞生
A::A(const A&) --------> a 诞生 // 这里就是 x 传入 f() 里面调用的 A::A(const A&)
&a = 0012FF60
A::A(const A&) --------> b 诞生 // 这是 b 初始化时调用的 A::A(const A&)
A::~A() --------> a 毁灭 // 函数 f() 调用完毕,里面的 a 就被回收销毁了
&b = 0012FF6E
A::~A() --------> x 毁灭
A::~A() --------> b 毁灭


问题就发生在这里,

A::A(const A&) --------> b 诞生 // 这是 b 初始化时调用的 A::A(const A&)

可能 return a; 跟 初始化 b 都是用同一个复制构造函数 A::A(const A&) 来完成的,所以它只需要调用一次就可以。
sankt 2006-04-26
  • 打赏
  • 举报
回复
#include <iostream>

class A
{
public:
A() { std::cout << "A::A()\n"; }
A(const A&) { std::cout << "A::A(const A&)\n"; }
~A() { std::cout << "A::~A()\n"; }
};

A f(A a)
{
std::cout << "&a" << &a << std::endl;
return a;
}

int main(int argc, char *argv[])
{
A x;

A b = f(x); // 这里传入x的时候会调用拷贝构造函数来创建一个临时对象.没有显示,是因为被编译器优化掉了

std::cout << "&b = " << &b << std::endl;

return 0;
}
leolovefun 2006-04-26
  • 打赏
  • 举报
回复
用VC++6.0测试,在A b = 的时候调用了一次A::A(const A&),在f(x)的return a的时候调用了一次A::A(const A&),析构了一次 共2次而已
foochow 2006-04-26
  • 打赏
  • 举报
回复
NVR
goodchan 2006-04-26
  • 打赏
  • 举报
回复
我明白了,是不是这样:


A::A() --------> x 诞生
A::A(const A&) --------> a 诞生
&a = 0012FF60
A::A(const A&) --------> b 诞生
A::~A() --------> a 毁灭
&b = 0012FF6E
A::~A() --------> x 毁灭
A::~A() --------> b 毁灭

A b = f(x); 就是 return a; 即只调用一次复制构造函数,用来产生 b
goodchan 2006-04-26
  • 打赏
  • 举报
回复
回复人:sixsavage(野人) ( 二级(初级)) 信誉:99 2006-04-26 11:37:00 得分:0

你的copy constructor运行了两次没有错啊
传递参数的时候一次,返回的时候一次
---------------------------------------------------

不会啊,用一个类型的物件来初始化另一个相同类型的新物件的时候,它会调用复制构造函数的啊。

例如: A a; A b = a; 这个时候会调用复制构造函数的。书上是这样说。

因此,A b = f(x); 返回一个 A 类型的临时对象,对同属于 A 类型的对象 b 进行初始化,应该会调用一次复制构造函数吧?

难道是因为它是一个临时的对象,所以不会调用复制构造函数?
---------------------------------------------------
---------------------------------------------------

回复人:believefym(暮色,miss,迷失,miss。。。) ( 一级(初级)) 信誉:100 2006-04-26 11:39:00 得分:0

return a不会调用拷贝构造函数,初始化b的时候调用了,所以还是三次
---------------------------------------------------

return a 的时候不是传值调用,因此会调用复制构造函数的吗?它返回的实际是一个 a 的临时复制品,而 a 本身被销毁。

而且输出只显示两次复制构造函数被调用啊。

64,654

社区成员

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

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