免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 3267 | 回复: 5

throw/catch究竟会不会复制一个对象? [复制链接]

论坛徽章:
0
发表于 2012-03-23 14:19 |显示全部楼层
20可用积分
本帖最后由 donet8 于 2012-03-23 16:07 编辑

More Effective C++上面说,要在catch语句里面使用引用,避免对象拷贝和阶段。
我用GCC和VC2010测试了一番,发现不论是否使用引用,似乎都不存在throw对象的拷贝-->似乎throw对象直接被放在了catch的空间里面,用不用&都是没有额外的拷贝。

但是这一来就无法解释,如果我在catch里面使用基类对象名,throw一个子类对象的时候,好像是会被截断。
但是,既然没有生成一个基类对象,从子类对象做截断拷贝(没有看到额外的拷贝函数调用),那么这个信息丢失又是如何发生的呢? 测试结果让我非常的疑惑啊:

  1. i#include"stdafx.h"
  2. struct base{
  3.     int i;
  4.     base(){
  5.         printf("base ctor\n");
  6.         i=2;
  7.     }
  8. };
  9. struct child: base{
  10.     child(){
  11.         printf("child ctor\n");
  12.         j=3;
  13.     }
  14.     int j;
  15. };
  16. using namespace std;
  17. int main(void){
  18.     string s1="abc";
  19.     string s2=s1;
  20.     printf("%p,%p\n",s1.c_str(),s2.c_str());

  21.     try{
  22.         throw child();
  23.     }catch(base b){
  24.         int*pi=(int*)&b;
  25.         printf("catch by value, c.i=%d,c.j=%d\n",pi[0],pi[1]);
  26.     }

  27.     try{
  28.         throw child();
  29.     }catch(base& b){
  30.         int*pi=(int*)&b;
  31.         printf("catch by ref, c.i=%d,c.j=%d\n",pi[0],pi[1]);
  32.     }
  33.    
  34.     try{
  35.         throw child();
  36.     }catch(child& c){
  37.         int*pi=(int*)&c;
  38.         printf("catch by ref, c.i=%d,c.j=%d\n",pi[0],pi[1]);
  39.     }
  40.     return 0;
  41. }
  42. //默认已经开启了SEH,什么选项?

复制代码
VC和GCC的测试结果一样的,都是下面这样:
base ctor
child ctor
catch by value, c.i=2,c.j=-858993460
base ctor
child ctor
catch by ref, c.i=2,c.j=3
base ctor
child ctor
catch by ref, c.i=2,c.j=3

论坛徽章:
14
巨蟹座
日期:2013-11-19 14:09:4615-16赛季CBA联赛之青岛
日期:2016-07-05 12:36:0515-16赛季CBA联赛之广东
日期:2016-06-29 11:45:542015亚冠之全北现代
日期:2015-07-22 08:09:472015年辞旧岁徽章
日期:2015-03-03 16:54:15巨蟹座
日期:2014-12-29 08:22:29射手座
日期:2014-12-05 08:20:39狮子座
日期:2014-11-05 12:33:52寅虎
日期:2014-08-13 09:01:31巳蛇
日期:2014-06-16 16:29:52技术图书徽章
日期:2014-04-15 08:44:01天蝎座
日期:2014-03-11 13:06:45
发表于 2012-03-23 14:19 |显示全部楼层
  1. #include <iostream>
  2. using namespace std;

  3. struct foo
  4. {
  5.     explicit foo( bool bshow=true ) : show_(bshow)
  6.     {
  7.         if( show_ ) cout << "[foo] constructor" << endl;
  8.     }
  9.     foo( const foo& rhs )
  10.     {
  11.         if( show_ ) cout << "[foo] copy constructor" << endl;
  12.     }
  13.     foo& operator=( const foo& rhs )
  14.     {
  15.         if( show_ ) cout << "[foo] assignation" << endl;
  16.         return *this;
  17.     }
  18.     virtual ~foo()
  19.     {
  20.         if( show_ ) cout << "[foo] destructor" << endl;
  21.     }

  22. private:
  23.     bool show_;
  24. };

  25. struct bar : foo
  26. {
  27.     bar() : foo(false)
  28.     {
  29.         cout << "[bar] constructor" << endl;
  30.     }
  31.     bar( const bar& rhs )
  32.     {
  33.         cout << "[bar] copy constructor" << endl;
  34.     }
  35.     bar& operator=( const bar& rhs )
  36.     {
  37.         cout << "[bar] assignation" << endl;
  38.         return *this;
  39.     }
  40.     virtual ~bar()
  41.     {
  42.         cout << "[bar] destructor" << endl;
  43.     }
  44. };

  45. int main()
  46. {
  47.     try {
  48.         throw foo();
  49.     } catch( foo ) {
  50.     }
  51.     cout << "---------------------" << endl;

  52.     try {
  53.         foo obj;
  54.         throw obj;
  55.     } catch( foo ) {
  56.     }
  57.     cout << "---------------------" << endl;

  58.     try {
  59.         throw foo();
  60.     } catch( const foo& ) {
  61.     }
  62.     cout << "---------------------" << endl;

  63.     try {
  64.         foo obj;
  65.         throw obj;
  66.     } catch( const foo& ) {
  67.     }
  68.     cout << "+++++++++++++++++++++" << endl;

  69.     try {
  70.         throw bar();
  71.     } catch( foo ) {
  72.     }
  73.     cout << "---------------------" << endl;

  74.     try {
  75.         bar obj;
  76.         throw obj;
  77.     } catch( foo ) {
  78.     }
  79.     cout << "---------------------" << endl;

  80.     try {
  81.         throw bar();
  82.     } catch( const foo& ) {
  83.     }
  84.     cout << "---------------------" << endl;

  85.     try {
  86.         bar obj;
  87.         throw obj;
  88.     } catch( const foo& ) {
  89.     }
  90.     cout << "+++++++++++++++++++++" << endl;

  91.     return 0;
  92. }
复制代码

论坛徽章:
0
发表于 2012-03-23 16:08 |显示全部楼层
不好意思。刚才代码没有贴全。
现在代码贴全了。

论坛徽章:
0
发表于 2012-03-23 16:16 |显示全部楼层
bruceteen 发表于 2012-03-23 15:17


OK,我就对着你的代码来说:
(1)

  1. try {
  2.         throw foo();
  3.     } catch( foo ) {
  4.     }
复制代码
第一个地方,throw foo()为什么只有一个ctor,一个dtor? 我期待的是既然catch里面没有使用引用符号,那么是不是被throw出来的这个foo应该被拷贝一份。
也就是ctor,copy ctor, dtor, dtor?

而实际上下面这种情况才是有一个拷贝的过程?

  1.     try {
  2.         foo obj;//先声明
  3.         throw obj;
  4.     } catch( foo ) {
  5.     }
复制代码
(2)下面这两种情况的差距怎么这么大:

  1.     try {
  2.         throw bar();
  3.     } catch( const foo& ) {
  4.     }
  5.     cout << "---------------------" << endl;

  6.     try {
  7.         bar obj;
  8.         throw obj;
  9.     } catch( const foo& ) {
  10.     }
复制代码
---------------------
[bar] constructor
[bar] destructor
---------------------
[bar] constructor
[foo] constructor
[bar] copy constructor
[bar] destructor
[bar] destructor
[foo] destructor

仅仅是多了一个声明bar的语句,就多了两个ctor和两个dtor.
这究竟怎么解释呢?

谢谢!

论坛徽章:
0
发表于 2012-03-23 16:27 |显示全部楼层
本帖最后由 donet8 于 2012-03-23 16:28 编辑

而且,如何解释我的程序中:

  1.     try{
  2.         throw child();
  3.     }catch(base b){
  4.         int*pi=(int*)&b;
  5.         printf("catch by value, c.i=%d,c.j=%d\n",pi[0],pi[1]);
  6.     }
复制代码
这里的child直接throw给catch(base),这里catch到的对象实际是一个child对象。
但是为什么printf发现它其实是一个base对象,没有child的成员j(=3)? 实际打印出来一个乱码。

如何解释呢?

论坛徽章:
0
发表于 2012-03-23 17:05 |显示全部楼层
我知道了,我没有在我的base/child里面实现copy ctor,所以没看出来。
现在我加上了,看出来了。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP