免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 1981 | 回复: 8
打印 上一主题 下一主题

[C++] 对象的构造和销毁的问题? [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-19 23:32 |只看该作者 |倒序浏览
5可用积分
struct Test
{
Test() {
     obj = new Obj();
     obj2 = new Obj2();
  }
~Test() {
    if (obj) delete obj;
    if (obj2) delete obj2;
}
Obj *obj;
Obj2 *obj2;
};

上面的Test对象有两个指针成员(不考虑auto_ptr),
假设在构造Obj和Obj2对象时,都有可能抛异常,
析构函数中必须要加if(obj) if(obj2) 判断吧?


谢谢

论坛徽章:
0
2 [报告]
发表于 2009-04-19 23:38 |只看该作者
加不加没区别,因为delete 0也是合法的(结果是什么都不做)

我觉得这样写应该会好些:
Test(): obj(0), obj2(0) {
     obj = new Obj();
     obj2 = new Obj2();
  }

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
3 [报告]
发表于 2009-04-20 00:10 |只看该作者
原帖由 nongdi 于 2009-4-19 23:32 发表
上面的Test对象有两个指针成员(不考虑auto_ptr),
假设在构造Obj和Obj2对象时,都有可能抛异常,
析构函数中必须要加if(obj) if(obj2) 判断吧?


如果Obj和Obj2要抛异常, 并且不考虑 auto_ptr ……  只能这样……

struct Test
{
Test() {
   
  }
~Test() {
    if (obj) delete obj;
    if (obj2) delete obj2;
}
Obj *obj;
Obj2 *obj2;
};

struct Test {
Test() {
    obj = new Obj(); // 如果抛异常, 不会有资源泄露。 Test构造函数的调用端会收到这个异常。
    try {
        obe2 = new Obj2(); // 这里就需要 try 保护
    }
    catch ( ... ) {
        delete obj; // 一旦出现任何异常, Test构造失败, 不会调用Test的析构函数, 需要自己释放obj
        throw;        // 重新抛出异常, 让Test构造函数的调用端处理这个异常
    }
}

~Test() {
  // 如果Test构造成功, 才会调用其析构。
  delete obj2; // 这2个指针肯定指向合法的对象
  delete obj;   // 当然, Test的其他操作必须合理
}

Test(const Test&);
Test& operator=(const Test&);
// 一旦包含指针成员, 通常需要考虑这2个函数的意义。
// 可以简单的将其禁止 —— 将它们声明为private
// 或者执行深拷贝
// 或者执行所有权转让

private:
  Obj* obj;
  Obj2* obj2;
};

论坛徽章:
0
4 [报告]
发表于 2009-04-20 00:35 |只看该作者
个人认为new 的异常最好在new里解决,自己重载new吧,每个类都加new delete异常处理的话
代码太。。。。

论坛徽章:
2
青铜圣斗士
日期:2015-11-26 06:15:59数据库技术版块每日发帖之星
日期:2016-07-24 06:20:00
5 [报告]
发表于 2009-04-20 00:46 |只看该作者
原帖由 hitraistlin 于 2009-4-20 00:35 发表
个人认为new 的异常最好在new里解决,自己重载new吧,每个类都加new delete异常处理的话
代码太。。。。


对楼主的问题, Obj、Obj2的构造函数如果需要抛异常, 肯定是构造出现了问题。
而构造出现问题, 最好的方式就是抛异常。

new重载、 或者不通过异常报告构造函数的错误, 只是逃避问题而已。

真正导致代码太那个的原因, 是楼主不考虑 auto_ptr (或者其他资源管理类)这个需求。
如果没有这个限制, 代码可以非常干净。

class Test {
    std::auto_ptr<Obj> obj1;
    std::auto_ptr<Obj2> obj2;
public:
    Test() : obj1(new Obj), obj2(new Obj2) { }
private:
    Test(const Test&);
    Test& operator=(const Test&);
};

论坛徽章:
0
6 [报告]
发表于 2009-04-20 08:51 |只看该作者
构造函数出现异常是不会调用析构函数

C++语言说:一个对象在出生的过程中出现问题,那这个对象就是一个没有生命的怪胎。既然它不是一个完整的对象,就根本不存在析构或释放的说法。

所以个人建议你用
Test() {
obj=NULL;
obj2=NULL;
try
{
     obj = new Obj();
     obj2 = new Obj2();
}
catch(...)
{
  delete obj; //C++里面delete NULL是合法的
  delete obj2;
  //有需要的话在此再抛异常以示构造不成功
}
}

论坛徽章:
223
2022北京冬奥会纪念版徽章
日期:2015-08-10 16:30:32操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-02-18 06:20:00操作系统版块每日发帖之星
日期:2016-03-01 06:20:00操作系统版块每日发帖之星
日期:2016-03-02 06:20:0015-16赛季CBA联赛之上海
日期:2019-09-20 12:29:3219周年集字徽章-周
日期:2019-10-01 20:47:4815-16赛季CBA联赛之八一
日期:2020-10-23 18:30:5320周年集字徽章-20	
日期:2020-10-28 14:14:2615-16赛季CBA联赛之广夏
日期:2023-02-25 16:26:26CU十四周年纪念徽章
日期:2023-04-13 12:23:10操作系统版块每日发帖之星
日期:2016-05-10 19:22:58
7 [报告]
发表于 2009-04-20 09:19 |只看该作者
原来所谓异常就是指,new到NULL了?

论坛徽章:
0
8 [报告]
发表于 2009-04-20 11:17 |只看该作者
谢谢各位的解答.
我想我应该记住:"构造函数出现异常是不会调用析构函数"这句话就可以了.
至于用不用auto_ptr那是另外一回事,毕竟auto_ptr不是万能的.
再次感谢!

论坛徽章:
223
2022北京冬奥会纪念版徽章
日期:2015-08-10 16:30:32操作系统版块每日发帖之星
日期:2016-05-10 19:22:58操作系统版块每日发帖之星
日期:2016-02-18 06:20:00操作系统版块每日发帖之星
日期:2016-03-01 06:20:00操作系统版块每日发帖之星
日期:2016-03-02 06:20:0015-16赛季CBA联赛之上海
日期:2019-09-20 12:29:3219周年集字徽章-周
日期:2019-10-01 20:47:4815-16赛季CBA联赛之八一
日期:2020-10-23 18:30:5320周年集字徽章-20	
日期:2020-10-28 14:14:2615-16赛季CBA联赛之广夏
日期:2023-02-25 16:26:26CU十四周年纪念徽章
日期:2023-04-13 12:23:10操作系统版块每日发帖之星
日期:2016-05-10 19:22:58
9 [报告]
发表于 2009-04-21 11:45 |只看该作者
try...catch...代码太麻烦了。


C++保证了析构函数一定会被调用,所以即使是有异常抛出,
原文:
http://www.stlchina.org/twiki/bin/view.pl/Main/BoostThread
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP