拷贝构造函数的问题

种菜的 2012-08-13 11:24:18
A是一个类名,包含一个int 成员变量 i 和一个指针成员变量,为了方便大家解决问题,就只写了对成员i的操作:

+操作符定义为成员:
A A::operator+(const A &obj)
{
A tmp;
tmp.i = i + obj.i;
return tmp;
}

A::A(const A &obj):i(obj.i)
{
std::cout << "A copy constructor" << std::endl;
}

1: A a1, a2;
2: A a3(a1 + a2); 或者 A a3 = a1 + a2;

按说在使用小括弧()初始化对象时应该使用拷贝构造函数把a1+a2后返回的的临时对象拷贝到a3,但是执行2时为什么没有调用拷贝构造函数?
...全文
184 17 打赏 收藏 转发到动态 举报
写回复
用AI写文章
17 条回复
切换为时间正序
请发表友善的回复…
发表回复
种菜的 2012-08-15
  • 打赏
  • 举报
回复
VC6.0,我也试过了,如果定义了自己的析构函数,就只调用一次拷贝构造,如果没有定义析构函数而用编译器提供的默认析构函数,就会调用两次拷贝构造函数,正如14楼的代码;

对于gcc,不管是否自己定义析构函数都不调用拷贝构造函数,用-O0也一样不调用,真是编译器的问题;
种菜的 2012-08-15
  • 打赏
  • 举报
回复
反了,应该是这样的:

1. 显示定义析构函数时,在调用加操作符返回临时对象后,将临时对象拷贝(调用了拷贝构造函数)到了a3,而在return tmp时缺没调用,这时本该调用的;

2. 不显示定义析构函数时,调用两次,return tmp时,调用一次,返回临时对象后对a3赋值时调用了拷贝构造函数;

和析构函数有关了!
种菜的 2012-08-15
  • 打赏
  • 举报
回复
1. 不显示定义析构函数时,在调用加操作符返回临时对象后,将临时对象拷贝(调用了拷贝构造函数)到了a3,而在return tmp时缺没调用,这时本该调用的;

2. 显示定义析构函数时,调用两次,return tmp时,调用一次,返回临时对象后对a3赋值时调用了拷贝构造函数;

和析构函数有关了!
种菜的 2012-08-14
  • 打赏
  • 举报
回复
就认为是编译器的原因吧,结贴。唉。
种菜的 2012-08-14
  • 打赏
  • 举报
回复
5楼做法把左操作数改变了,是不合适的。
god402093272 2012-08-14
  • 打赏
  • 举报
回复
这是我用VC做的 结果不错
#include<iostream.h>

class A
{
int i;
public:
A(int j=0):i(0){};
A operator+(const A &b);
A(const A& b);
};

A A::operator+(const A &b)
{
A tmp;
tmp.i = tmp.i + b.i;
return tmp;
}

A::A(const A &b)
{
cout << "A copy constructor" <<endl;
}
int main()
{
A a1, a2;
A a3(a1 + a2);
return 0;
}
种菜的 2012-08-13
  • 打赏
  • 举报
回复
嗯,谢谢你们的解答,原来有同学也遇到了,原来和编译器有关,真不厚道,我用的gcc 版本 4.4.6 20110731,那该用VC6.0试试。

rmaly 2012-08-13
  • 打赏
  • 举报
回复
A& A::operator+(const A &obj)
{
this->i = this->i + obj.i;
return *this;
}
改成这样就可以了
微型蚂蚁 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 的回复:]
引用楼主 的回复:
A是一个类名,包含一个int 成员变量 i 和一个指针成员变量,为了方便大家解决问题,就只写了对成员i的操作:

+操作符定义为成员:
A A::operator+(const A &amp;obj)
{
A tmp;
tmp.i = i + obj.i;
return tmp;
}

A::A(const A &amp;obj):i(ob……
[/Quote]
刚刚试了一下用gcc -O0编译依然没有调用拷贝构造。。。
难道这种优化是关不掉的。
willYanwill 2012-08-13
  • 打赏
  • 举报
回复
我也遇到过这种问题,当时问老师,几种情况下会调用拷贝函数:初始化、函数类类型参数传递、还有就是你这个函数返回类对象。为什么我的返回类对象是没有调用拷贝构造函数,当时也把老师难住了。后来查了很多资料弄了好几天才明白,是编译器的问题,我用的cfree,貌似不支持这个,你换个编译器应该就可以了,试试看吧,祝你成功!
pathuang68 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用楼主 的回复:]
A是一个类名,包含一个int 成员变量 i 和一个指针成员变量,为了方便大家解决问题,就只写了对成员i的操作:

+操作符定义为成员:
A A::operator+(const A &obj)
{
A tmp;
tmp.i = i + obj.i;
return tmp;
}

A::A(const A &obj):i(obj.i)
{
st……
[/Quote]
被编译器优化掉了。
hello_kitty8888 2012-08-13
  • 打赏
  • 举报
回复
A a3(a1 + a2);这一句中括号中的值生成的是一个临时变量,也就是说括号执行完后,这个变量就会消失,而复制构造函数传的是一个引用,用的也不是这个复制构造函数。也就是说tmp变量遇到右花括号已经析构了,不存在了。
5楼应该是正解,
种菜的 2012-08-13
  • 打赏
  • 举报
回复
同学们,能否说明下是怎么发现被编译器优化掉的吗?
rmaly 2012-08-13
  • 打赏
  • 举报
回复
是啊,编译器的问题
[Quote=引用 6 楼 的回复:]

嗯,谢谢你们的解答,原来有同学也遇到了,原来和编译器有关,真不厚道,我用的gcc 版本 4.4.6 20110731,那该用VC6.0试试。
[/Quote]
种菜的 2012-08-13
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

A& A::operator+(const A &obj)
{
this->i = this->i + obj.i;
return *this;
}
改成这样就可以了
[/Quote]

这样岂不是把左操作数也修改了,实际不应该修改的,应该返回两个对象之和的一个副本,而不是左操作数本身的引用,不知道这样能不能编译通过,至少返回值类型应该是值类型,而不是引用。

64,642

社区成员

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

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