c++构造函数中发生错误,如何处理? http://www.opengpu.org/forum.php?mod=viewthread&tid=2918
来源:互联网 发布:南木梁知txt 编辑:程序博客网 时间:2024/05/22 23:59
c++构造函数中发生错误,如何处理?
骑都尉(从五品)
本帖最后由 songge09 于 2010-6-30 17:37 编辑
如果构造函数中发生错误,如何处理较为妥当?不要说构造函数中不可能发生错误,那要么是你没有处理,要么是总是空的构造函数。
我目前得方法是这样的
但总觉得这样是不是太c style了,并不是说c style不好,而是c++本身的style是什么?
c++作者搞了个raii的方案,我不喜欢,不够kiss。
望牛哥指点。
如果构造函数中发生错误,如何处理较为妥当?不要说构造函数中不可能发生错误,那要么是你没有处理,要么是总是空的构造函数。
我目前得方法是这样的
但总觉得这样是不是太c style了,并不是说c style不好,而是c++本身的style是什么?
c++作者搞了个raii的方案,我不喜欢,不够kiss。
望牛哥指点。
分享收藏000
使用道具 举报
上轻车都尉(正四品)
我会尽量减少在构造函数里的工作量,尽量往外移,构造函数尽可能仅赋值,以及进行无IO、无异步的内部构建。。。。
- 1
查看全部评分
使用道具 举报
骑都尉(从五品)
是的,析构函数同样有这个问题,所以我现在不得不把大部分类都加上
init
destroy
这两个函数,并显示调用判别并处理错误。
但是这样,构造函数和析构函数就完全变成无用的东西了
init
destroy
这两个函数,并显示调用判别并处理错误。
但是这样,构造函数和析构函数就完全变成无用的东西了
使用道具 举报
上柱国(正二品)
构造函数中的错误一般通过抛出异常来处理
- 1
查看全部评分
使用道具 举报
轻车都尉(从四品)
嗯, 一般只用它初始化变量
使用道具 举报
上轻车都尉(正四品)
这是有问题的,构造函数,不应该抛出异常,考虑
这个情况就相当尴尬了,构造函数一旦抛出异常,a 根本就没有赋值,也就是说,new 的结果泄露了。
构造函数和析构函数是一定不能抛出异常的,否则将引来更多问题。
使用道具 举报
骑都尉(从五品)
本帖最后由 songge09 于 2010-7-1 12:14 编辑
new 失败会产生异常,如果不catch异常,那么怎么得知出现了错误呢?
new失败了,就证明内存没有分配,何来泄露之说呢?或者new失败是由于AClass的构造函数调用失败造成的,但是AClass的构造函数应该会catch这个异常并处理,而不是继续抛出吧。
我是比较反对仅仅在构造函数里写 pointer = 0; 这样的语句,完全没什么作用么。
我认为 Creation = Initializition,这也应该是c++本身所倡导的。
new 失败会产生异常,如果不catch异常,那么怎么得知出现了错误呢?
new失败了,就证明内存没有分配,何来泄露之说呢?或者new失败是由于AClass的构造函数调用失败造成的,但是AClass的构造函数应该会catch这个异常并处理,而不是继续抛出吧。
我是比较反对仅仅在构造函数里写 pointer = 0; 这样的语句,完全没什么作用么。
我认为 Creation = Initializition,这也应该是c++本身所倡导的。
使用道具 举报
超级版主
本帖最后由 lidudu 于 2010-7-2 10:31 编辑
构造函数执行时,对象的内存已经分配了。
按C++ Spec,构造函数抛异常时,会立刻执行已成功构造的成员对象的析构函数并释放内存。所以不会有内存泄露。
但是,这并不意味着没问题了,因为在析构函数里,你并不知道哪些成员已经初始化了而需要delete,这意味着需要在构造函数初始化列表里将指针都初始化成NULL,然后再构造函数体内创建对象赋值,这样析构才能判断。
即便不会出错误了,要满足C++ spec意味着编译器要对每个可能抛异常的构造的new操作自动生成一个try-catch来调用析构和释放内存。在意性能的程序员会很心痛~心痛~心痛~
所以,便有了构造析构不干活,而另做init()/destroy()的用法。
但C++创始人strovstrup认为应该用Resource Acqusition is Initialization的模式,也就是要用构造和析构。但出错时未必要抛异常,而可以将对象置于无效状态,如file("abc.txt")构造后,如果文件不存在,那么if (file) 为假。这个方法的麻烦就是构造之后要多做一步检查,但总比init()/destroy()简单。
构造函数执行时,对象的内存已经分配了。
按C++ Spec,构造函数抛异常时,会立刻执行已成功构造的成员对象的析构函数并释放内存。所以不会有内存泄露。
即便不会出错误了,要满足C++ spec意味着编译器要对每个可能抛异常的构造的new操作自动生成一个try-catch来调用析构和释放内存。在意性能的程序员会很心痛~心痛~心痛~
所以,便有了构造析构不干活,而另做init()/destroy()的用法。
但C++创始人strovstrup认为应该用Resource Acqusition is Initialization的模式,也就是要用构造和析构。但出错时未必要抛异常,而可以将对象置于无效状态,如file("abc.txt")构造后,如果文件不存在,那么if (file) 为假。这个方法的麻烦就是构造之后要多做一步检查,但总比init()/destroy()简单。
- 1
查看全部评分
使用道具 举报
骑都尉(从五品)
标准方法: 抛异常
使用道具 举报
骑都尉(从五品)
回复 8# lidudu
回答的好!
回答的好!
使用道具 举报
超级版主
本帖最后由 lidudu 于 2010-7-2 10:39 编辑
纠正一下,前面说的有错。当new obj()抛异常时,obj.~obj()不会执行,但其已经成功初始化的成员对象的析构会被执行。也就是说,成功分配内存的单纯的指针成员变量会导致内存泄露,所以必须用smart_ptr这种带析构函数的包装。
另外,即使构造函数没有抛异常,但任何new运算符都可能因为out of memory抛异常(按C++ spec),那么理论上编译器总要在new外边套一层try-catch,才能保证正确释放资源。这个比较郁闷。
不论如何,C++的构造函数里最好还是避免异常,析构更是。STL里绝大多数类的构造都不抛异常。当然,这个不是太有说服力,因为STL最早出现时,C++还没有异常处理这个特性呢。
对于异常方面的问题,可以参考http://yosefk.com/c++fqa/exceptions.html#fqa-17.2
纠正一下,前面说的有错。当new obj()抛异常时,obj.~obj()不会执行,但其已经成功初始化的成员对象的析构会被执行。也就是说,成功分配内存的单纯的指针成员变量会导致内存泄露,所以必须用smart_ptr这种带析构函数的包装。
另外,即使构造函数没有抛异常,但任何new运算符都可能因为out of memory抛异常(按C++ spec),那么理论上编译器总要在new外边套一层try-catch,才能保证正确释放资源。这个比较郁闷。
不论如何,C++的构造函数里最好还是避免异常,析构更是。STL里绝大多数类的构造都不抛异常。当然,这个不是太有说服力,因为STL最早出现时,C++还没有异常处理这个特性呢。
对于异常方面的问题,可以参考http://yosefk.com/c++fqa/exceptions.html#fqa-17.2
使用道具 举报
骑都尉(从五品)
对于异常方面的问题,可以参考http://yosefk.com/c++fqa/exceptions.html#fqa-17.2
lidudu,谢谢,这个上面的资料正是我想搞清楚的东西,你真有学问
lidudu,谢谢,这个上面的资料正是我想搞清楚的东西,你真有学问
使用道具 举报
头像被屏蔽
禁止访问
使用道具 举报
上轻车都尉(正四品)
没有深入研究过,学习.
貌似这里的氛围不错,是个好地方.
貌似这里的氛围不错,是个好地方.
使用道具 举报
云骑尉(正七品)
构造函数只做成员变量的默认值的赋与,大量的操作还是放在Init()函数的好。
使用道具 举报
上骑都尉(正五品)
本帖最后由 lisa 于 2010-8-17 18:52 编辑
并不是要靠try-catch才能保证正确释放资源的,调new的话最终会掉MSVCR90(D).dll这类CRT的函数(如果调试debug版的CRT会发现调new的话会调malloc,然后是一系列的debug版malloc实现,非常多,最终有一个函数调了HeapAlloc,release比较简单,最终也是调HeapAlloc),最终由HeapAlloc、VirtualAlloc这类函数负责分配内存,当程序结束时进程负责摧毁所有的堆(如果没掉HeapCreate的话就一个默认堆),堆摧毁时内存就释放了,所以编译器并不需要去给new加try-catch来保证资源被释放的,CRT会加try-catch,但它不是为了正确释放内存用的。
并不是要靠try-catch才能保证正确释放资源的,调new的话最终会掉MSVCR90(D).dll这类CRT的函数(如果调试debug版的CRT会发现调new的话会调malloc,然后是一系列的debug版malloc实现,非常多,最终有一个函数调了HeapAlloc,release比较简单,最终也是调HeapAlloc),最终由HeapAlloc、VirtualAlloc这类函数负责分配内存,当程序结束时进程负责摧毁所有的堆(如果没掉HeapCreate的话就一个默认堆),堆摧毁时内存就释放了,所以编译器并不需要去给new加try-catch来保证资源被释放的,CRT会加try-catch,但它不是为了正确释放内存用的。
使用道具 举报
护军(从三品)
一开始是无序状态,构造函数使对象变成"空"的状态,Init()使它变成"有内容"的状态,Clear()使它变回"空"的状态,析构函数使它变回无序状态,这样比较清楚.
使用道具 举报
骑都尉(从五品)
本帖最后由 socket9999 于 2010-8-19 14:12 编辑
这个问题貌似C++ Primer和Effective C++里都提到过。
解决方法是把a改成智能指针,这样a被销毁时也会delete所指对象。
这个问题貌似C++ Primer和Effective C++里都提到过。
解决方法是把a改成智能指针,这样a被销毁时也会delete所指对象。
c++构造函数中发生错误,如何处理?
骑都尉(从五品)
本帖最后由 songge09 于 2010-6-30 17:37 编辑
如果构造函数中发生错误,如何处理较为妥当?不要说构造函数中不可能发生错误,那要么是你没有处理,要么是总是空的构造函数。
我目前得方法是这样的
但总觉得这样是不是太c style了,并不是说c style不好,而是c++本身的style是什么?
c++作者搞了个raii的方案,我不喜欢,不够kiss。
望牛哥指点。
如果构造函数中发生错误,如何处理较为妥当?不要说构造函数中不可能发生错误,那要么是你没有处理,要么是总是空的构造函数。
我目前得方法是这样的
但总觉得这样是不是太c style了,并不是说c style不好,而是c++本身的style是什么?
c++作者搞了个raii的方案,我不喜欢,不够kiss。
望牛哥指点。
分享收藏000
使用道具 举报
上轻车都尉(正四品)
我会尽量减少在构造函数里的工作量,尽量往外移,构造函数尽可能仅赋值,以及进行无IO、无异步的内部构建。。。。
- 1
查看全部评分
使用道具 举报
骑都尉(从五品)
是的,析构函数同样有这个问题,所以我现在不得不把大部分类都加上
init
destroy
这两个函数,并显示调用判别并处理错误。
但是这样,构造函数和析构函数就完全变成无用的东西了
init
destroy
这两个函数,并显示调用判别并处理错误。
但是这样,构造函数和析构函数就完全变成无用的东西了
使用道具 举报
上柱国(正二品)
构造函数中的错误一般通过抛出异常来处理
- 1
查看全部评分
使用道具 举报
轻车都尉(从四品)
嗯, 一般只用它初始化变量
使用道具 举报
上轻车都尉(正四品)
这是有问题的,构造函数,不应该抛出异常,考虑
这个情况就相当尴尬了,构造函数一旦抛出异常,a 根本就没有赋值,也就是说,new 的结果泄露了。
构造函数和析构函数是一定不能抛出异常的,否则将引来更多问题。
使用道具 举报
骑都尉(从五品)
本帖最后由 songge09 于 2010-7-1 12:14 编辑
new 失败会产生异常,如果不catch异常,那么怎么得知出现了错误呢?
new失败了,就证明内存没有分配,何来泄露之说呢?或者new失败是由于AClass的构造函数调用失败造成的,但是AClass的构造函数应该会catch这个异常并处理,而不是继续抛出吧。
我是比较反对仅仅在构造函数里写 pointer = 0; 这样的语句,完全没什么作用么。
我认为 Creation = Initializition,这也应该是c++本身所倡导的。
new 失败会产生异常,如果不catch异常,那么怎么得知出现了错误呢?
new失败了,就证明内存没有分配,何来泄露之说呢?或者new失败是由于AClass的构造函数调用失败造成的,但是AClass的构造函数应该会catch这个异常并处理,而不是继续抛出吧。
我是比较反对仅仅在构造函数里写 pointer = 0; 这样的语句,完全没什么作用么。
我认为 Creation = Initializition,这也应该是c++本身所倡导的。
使用道具 举报
超级版主
本帖最后由 lidudu 于 2010-7-2 10:31 编辑
构造函数执行时,对象的内存已经分配了。
按C++ Spec,构造函数抛异常时,会立刻执行已成功构造的成员对象的析构函数并释放内存。所以不会有内存泄露。
但是,这并不意味着没问题了,因为在析构函数里,你并不知道哪些成员已经初始化了而需要delete,这意味着需要在构造函数初始化列表里将指针都初始化成NULL,然后再构造函数体内创建对象赋值,这样析构才能判断。
即便不会出错误了,要满足C++ spec意味着编译器要对每个可能抛异常的构造的new操作自动生成一个try-catch来调用析构和释放内存。在意性能的程序员会很心痛~心痛~心痛~
所以,便有了构造析构不干活,而另做init()/destroy()的用法。
但C++创始人strovstrup认为应该用Resource Acqusition is Initialization的模式,也就是要用构造和析构。但出错时未必要抛异常,而可以将对象置于无效状态,如file("abc.txt")构造后,如果文件不存在,那么if (file) 为假。这个方法的麻烦就是构造之后要多做一步检查,但总比init()/destroy()简单。
构造函数执行时,对象的内存已经分配了。
按C++ Spec,构造函数抛异常时,会立刻执行已成功构造的成员对象的析构函数并释放内存。所以不会有内存泄露。
即便不会出错误了,要满足C++ spec意味着编译器要对每个可能抛异常的构造的new操作自动生成一个try-catch来调用析构和释放内存。在意性能的程序员会很心痛~心痛~心痛~
所以,便有了构造析构不干活,而另做init()/destroy()的用法。
但C++创始人strovstrup认为应该用Resource Acqusition is Initialization的模式,也就是要用构造和析构。但出错时未必要抛异常,而可以将对象置于无效状态,如file("abc.txt")构造后,如果文件不存在,那么if (file) 为假。这个方法的麻烦就是构造之后要多做一步检查,但总比init()/destroy()简单。
- 1
查看全部评分
使用道具 举报
骑都尉(从五品)
标准方法: 抛异常
使用道具 举报
骑都尉(从五品)
回复 8# lidudu
回答的好!
回答的好!
使用道具 举报
超级版主
本帖最后由 lidudu 于 2010-7-2 10:39 编辑
纠正一下,前面说的有错。当new obj()抛异常时,obj.~obj()不会执行,但其已经成功初始化的成员对象的析构会被执行。也就是说,成功分配内存的单纯的指针成员变量会导致内存泄露,所以必须用smart_ptr这种带析构函数的包装。
另外,即使构造函数没有抛异常,但任何new运算符都可能因为out of memory抛异常(按C++ spec),那么理论上编译器总要在new外边套一层try-catch,才能保证正确释放资源。这个比较郁闷。
不论如何,C++的构造函数里最好还是避免异常,析构更是。STL里绝大多数类的构造都不抛异常。当然,这个不是太有说服力,因为STL最早出现时,C++还没有异常处理这个特性呢。
对于异常方面的问题,可以参考http://yosefk.com/c++fqa/exceptions.html#fqa-17.2
纠正一下,前面说的有错。当new obj()抛异常时,obj.~obj()不会执行,但其已经成功初始化的成员对象的析构会被执行。也就是说,成功分配内存的单纯的指针成员变量会导致内存泄露,所以必须用smart_ptr这种带析构函数的包装。
另外,即使构造函数没有抛异常,但任何new运算符都可能因为out of memory抛异常(按C++ spec),那么理论上编译器总要在new外边套一层try-catch,才能保证正确释放资源。这个比较郁闷。
不论如何,C++的构造函数里最好还是避免异常,析构更是。STL里绝大多数类的构造都不抛异常。当然,这个不是太有说服力,因为STL最早出现时,C++还没有异常处理这个特性呢。
对于异常方面的问题,可以参考http://yosefk.com/c++fqa/exceptions.html#fqa-17.2
使用道具 举报
骑都尉(从五品)
对于异常方面的问题,可以参考http://yosefk.com/c++fqa/exceptions.html#fqa-17.2
lidudu,谢谢,这个上面的资料正是我想搞清楚的东西,你真有学问
lidudu,谢谢,这个上面的资料正是我想搞清楚的东西,你真有学问
使用道具 举报
头像被屏蔽
禁止访问
使用道具 举报
上轻车都尉(正四品)
没有深入研究过,学习.
貌似这里的氛围不错,是个好地方.
貌似这里的氛围不错,是个好地方.
使用道具 举报
云骑尉(正七品)
构造函数只做成员变量的默认值的赋与,大量的操作还是放在Init()函数的好。
使用道具 举报
上骑都尉(正五品)
本帖最后由 lisa 于 2010-8-17 18:52 编辑
并不是要靠try-catch才能保证正确释放资源的,调new的话最终会掉MSVCR90(D).dll这类CRT的函数(如果调试debug版的CRT会发现调new的话会调malloc,然后是一系列的debug版malloc实现,非常多,最终有一个函数调了HeapAlloc,release比较简单,最终也是调HeapAlloc),最终由HeapAlloc、VirtualAlloc这类函数负责分配内存,当程序结束时进程负责摧毁所有的堆(如果没掉HeapCreate的话就一个默认堆),堆摧毁时内存就释放了,所以编译器并不需要去给new加try-catch来保证资源被释放的,CRT会加try-catch,但它不是为了正确释放内存用的。
并不是要靠try-catch才能保证正确释放资源的,调new的话最终会掉MSVCR90(D).dll这类CRT的函数(如果调试debug版的CRT会发现调new的话会调malloc,然后是一系列的debug版malloc实现,非常多,最终有一个函数调了HeapAlloc,release比较简单,最终也是调HeapAlloc),最终由HeapAlloc、VirtualAlloc这类函数负责分配内存,当程序结束时进程负责摧毁所有的堆(如果没掉HeapCreate的话就一个默认堆),堆摧毁时内存就释放了,所以编译器并不需要去给new加try-catch来保证资源被释放的,CRT会加try-catch,但它不是为了正确释放内存用的。
使用道具 举报
护军(从三品)
一开始是无序状态,构造函数使对象变成"空"的状态,Init()使它变成"有内容"的状态,Clear()使它变回"空"的状态,析构函数使它变回无序状态,这样比较清楚.
使用道具 举报
骑都尉(从五品)
本帖最后由 socket9999 于 2010-8-19 14:12 编辑
这个问题貌似C++ Primer和Effective C++里都提到过。
解决方法是把a改成智能指针,这样a被销毁时也会delete所指对象。
这个问题貌似C++ Primer和Effective C++里都提到过。
解决方法是把a改成智能指针,这样a被销毁时也会delete所指对象。
0 0
- c++构造函数中发生错误,如何处理? http://www.opengpu.org/forum.php?mod=viewthread&tid=2918
- http://www.apkbus.com/forum.php?mod=viewthread&tid=19181
- http://www.eoeandroid.com/forum.php?mod=viewthread&tid=165974
- http://www.discuz.net/forum.php?mod=viewthread&tid=611716&page=1&authorid=13759
- http://www.devdiv.com/forum.php?mod=viewthread&tid=43010&highlight=%C1%A3%D7%D3
- http://www.whitecell.org/forums/viewthread.php?tid=343
- 加速度计的理解 http://www.geek-workshop.com/forum.php?mod=viewthread&tid=1695&highlight=%D6%B8%C4%CF
- 分享45个android实例源码,很好很强大.收藏吧!!! http://www.apkbus.com/forum.php?mod=viewthread&tid=20978 (出处: Android开
- 【转帖】对通用输入输出GPIO的深入理解http://www.9mcu.com/9mcubbs/forum.php?mod=viewthread&tid=954521(出处: 大连创客空间)
- 类UNIX系统基础:文件安全与权限 http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=434579
- forum.php?mod=viewthread&tid=5540142&page=1&extra=#pid6812375
- http://www.cgbolo.com/viewthread.php?tid=13334
- deepin-15.4下Qt软件开发环境的搭建步骤 来自deepin社区 https://bbs.deepin.org/forum.php?mod=viewthread&tid=137949
- 数据挖掘常用算法及实现(http://bbs.chinakdd.com/forum.php?mod=viewthread&tid=4055&extra=page%3D1)
- 【入门】一次线上靶场writeup http://bbs.ichunqiu.com/forum.php?mod=viewthread&tid=16009&fromuid=195551 (出处: i春秋
- 大内高手—内存模型 http://www.it221.cn/viewthread.php?tid=806
- 使用dup2重定向了标准输出后,使用什么方法恢复对终端的输出?? http://bbs.chinaunix.net/forum.php?mod=viewthread&tid=359433&page=
- 集成安装光盘制作教程(http://bbs.deepin.org/viewthread.php?tid=1170144)
- python 爬虫小记
- 《C++并发编程实战》读书笔记1---多线程基本使用
- poj Phone List 3630 (字典树 判断前缀)
- (一)如何成为wine开发者
- 接口interface的应用和工厂方法模式
- c++构造函数中发生错误,如何处理? http://www.opengpu.org/forum.php?mod=viewthread&tid=2918
- linux下的find文件查找命令与grep文件内容查找命令
- pkg文件--一种简单的游戏资源打包格式
- Android 基于ImageSwitcher实现的左右切换图片
- 通用异常处理框架
- 完整删除pod,解决某些无法解决的问题
- 用while循环计算1+1/2!+1/3!+1/4!...+1/20!(BigDecimal精确计算小数)
- Android——处理设备旋转Activity销毁时临时数据丢失的问题
- 【Android】图片切换组件ImageSwitcher的运用