问一个构造函数和复制构造函数的问题

updd 2004-11-02 12:10:07
我的类是这么定义的。
class Ex
{
private:
int num;
const char *pStr;
public:
Ex(int x,const char *p)
{
num=x;
pStr=p;
cout<<"Constructing"<<x<<"..."<<endl;
}
Ex(const Ex& tmp)
{
num=tmp.num;
pStr=tmp.pStr;
cout<<"Copy constructing"<<tmp.num<<"..."<<endl;
}
~Ex()
{
cout<<"destructing..."<<endl;
}
};

主函数是
void main()
{
Ex x(1,"abcd"),y(2,"asdg");
Ex z[2]={Ex(3,"asdf"),Ex(4,"sdgasdg")};
}
问题就是:
如果我没有那个析构函数~Ex(),那么就会显示调用了两次复制构造函数。
Constructing1...
Constructing2...
Constructing3...
Copy constructing3...
Constructing4...
Copy constructing4...
但定义了那个析构函数~Ex()后,就没有调用那两次复制构造函数了。
Constructing1...
Constructing2...
Constructing3...
Constructing4...
destructing...
destructing...
destructing...
destructing...

为什么啊?
...全文
144 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
updd 2004-11-02
  • 打赏
  • 举报
回复
自定义了析构函数就没调用了。
没自定义就调用了,
奇怪啊
dragonzxh 2004-11-02
  • 打赏
  • 举报
回复
NRV
lazyboya 2004-11-02
  • 打赏
  • 举报
回复
是啊,不过好像没有调用拷贝构造函数.
updd 2004-11-02
  • 打赏
  • 举报
回复
我也是VC6.0啊。
我觉得
Ex z[2]={Ex(3,"asdf"),Ex(4,"sdgasdg")};
这里肯定是调用两次构造函数和两次复制构造函数啊
mxk130 2004-11-02
  • 打赏
  • 举报
回复
你用得啥环境?我这里运行了一下,没有出现调用拷贝构造函数。
有析构函数:Constructing1...
Constructing2...
Constructing3...
Constructing4...
destructing...
destructing...
destructing...
destructing...

没析构函数:
Constructing1...
Constructing2...
Constructing3...
Constructing4...

我用的是vc6.0

imRainman 2004-11-02
  • 打赏
  • 举报
回复
是地~~~

updd兄客气了,同门兄弟互相帮助嘛~
updd 2004-11-02
  • 打赏
  • 举报
回复
雨人,谢谢你,我明白了。
考虑到缺省复制构造函数是浅拷贝,释放掉临时对象的堆资源,会造成需要的对象指针悬空。所以编译器做了这样的处理,对不对?
imRainman 2004-11-02
  • 打赏
  • 举报
回复
系统会加上一个无能的析构函数

他什么也不做

所以可以保证安全~
bshaozi 2004-11-02
  • 打赏
  • 举报
回复
楼上这位朋友
你的意识是说在自己没有定义析构函数的话
那系统就不会只动加上析构函数了么?
好像不对吧~
imRainman 2004-11-02
  • 打赏
  • 举报
回复
在VC6的某个版本以前,对标准支持的不是很好,就出现了这种问题。

这也是个临时对象的问题,下面简单说明一下:

楼主是这样定义变量的:

Ex z[2]={Ex(3,"asdf"),Ex(4,"sdgasdg")};

在VC6的某个版本以前,编译器是这样做的:

1. 生成一个临时对象a保存Ex(3,"asdf")的值

2. 拷贝临时对象a到z[0]中

3. 销毁临时对象a

4. 生成一个临时对象b保存Ex(4,"sdgasdg")的值

5. 拷贝临时对象b到z[0]中

6. 销毁临时对象a

这就是楼主所看到:
Constructing3...
Copy constructing3...
Constructing4...
Copy constructing4...
的原因。

但当楼主定义了析构函数以后,编译器就不能再这样干了,为什么呢?

举个简单的例子:

如果在构造函数中分配内存,在析构函数中释放,那么当拆除临时对象的时候,内存被释放了。

但刚刚通过拷贝成生的对象却还要使用这块内存,这样会造成不可测的结果。

于是编译器采取如下办法构造上面两个变量:

1. 生成一个临时对象a保存Ex(3,"asdf")的值

2. 直接将这个对象作为z[0]返回给用户

3. 生成一个临时对象b保存Ex(4,"sdgasdg")的值

4. 直接将这个对象作为z[1]返回给用户

这就是楼主后来只看到:
Constructing1...
Constructing2...
Constructing3...
Constructing4...
的原因。

VC6在以后的版本中(当然包括VC7)更好的支持了国际标准,使得临时变量的使用更加规范,而且编译

器编译出的代码也更加精减。如果大家使用的是后期的版本,那么不管你有没有析构函数,编译器都

是通过第二种方法构造这些变量的。
updd 2004-11-02
  • 打赏
  • 举报
回复
那篇帖子我看了,那个例子中,我去掉它的析构函数,同样出现了两次复制构造函数调用,加上析构函数,就没有了。这个也是NRV优化技术的结果吗?
xuzheng318 2004-11-02
  • 打赏
  • 举报
回复
mark!
dragonzxh 2004-11-02
  • 打赏
  • 举报
回复
http://blog.csdn.net/ajoo/archive/2002/06/24/16555.aspx

关于此讨论见此帖
http://community.csdn.net/Expert/topic/3495/3495574.xml

64,646

社区成员

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

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