C++析构函数为什么不能有返回值

恋喵大鲤鱼 深圳市腾讯计算机系统有限公司 高级软件工程师  2016-09-14 06:54:33
C++析构函数为什么要这样设计?我知道C++构造函数不能有返回值是因为构造函数返回this指针,但析够函数为何不能有返回值呢?
...全文
873 点赞 收藏 36
写回复
36 条回复
切换为时间正序
当前发帖距今超过3年,不再开放新的回复
发表回复
ID870177103 2016-09-19
1,析抅函数不需要检查有没有成功,因为它不应该失败,否则你应该把失败处理也放在这个类的析抅函数中,试想你释放内存即使失败了你能干嘛
2,析抅函数抛出异常,则这个类的成员不能正常析抅,如果一个类不能保证被析抅的话,说明发生内存泄露的可能很大,严重的错误
3,new函数(运算符)做两件事,分配内存,然后调用构造函数,最后返回这个地址,你说的那个new的重载接受一个地址,然后调用构造函数,最后返回,运算符是一种语法糖,构造函数是没有返回值的
回复
lm_whales 2016-09-19
构造函数实际上是这么做的 ----------- 1)基类(子对象)初始化 2)成员变量初始化,如果有虚函数,要初始化虚函数表,虚函数表的重写也在这里完成 3)函数体执行 这些步骤,编译后,都是在构造函数内部的。 编译器前: 1)2)两步,或者没写,或者写在初始化表中。 有些是隐性的代码,构造函数中没出现的基类(子对象),和成员函数初始化,虚函数表指针初始化, 有些是显式的代码,初始化表中出现。以及C++11 类内初始化(没有被初始化表覆盖的部分)。 只有第3步,构造函数的函数体,是一定会写的,哪怕是空函数体。 析构函数, 分一下几个步骤执行: 1) 析构函数的函数体 内代码 2)析构每个成员变量,修改虚函数表(指针) 3)析构基类子对象 析构函数。只有第一步是定义函数时候,必须写的。 后面两步。都没有任何可见代码。自动执行的。 如果有返回值,要等到第3步执行后,才能返回。 析构函数,返回个值,实际上也不能做什么。 因为对象已经不存在了,生命周期结束了。 。。。。。。。。。。。。。。。。。 构造函数,虽然没有返回值。 但是我们可以用 A a=A(); a = A(); 直接得到一个对象。 实际上,构造函数,相当于,返回了他构造的那个对象。 至少效果上,相当于有返回值的。 所以,构造函数,没有必要再弄个返回值出来了。
回复
恋喵大鲤鱼 2016-09-19
引用 35 楼 ID870177103 的回复:
1,析抅函数不需要检查有没有成功,因为它不应该失败,否则你应该把失败处理也放在这个类的析抅函数中,试想你释放内存即使失败了你能干嘛 2,析抅函数抛出异常,则这个类的成员不能正常析抅,如果一个类不能保证被析抅的话,说明发生内存泄露的可能很大,严重的错误 3,new函数(运算符)做两件事,分配内存,然后调用构造函数,最后返回这个地址,你说的那个new的重载接受一个地址,然后调用构造函数,最后返回,运算符是一种语法糖,构造函数是没有返回值的
基本上可以这么理解吧!
回复
恋喵大鲤鱼 2016-09-18
引用 19 楼 fefe82 的回复:
析构函数的调用是一个对象生命结束的标志。 一旦析构函数返回,对对象的任何操作,包括访问任何成员变量,成员函数都不再合法。 使用析构函数的返回值报告错误,知道出错之后,能做些什么呢?
可以在出错之后,可以abort程序然后log,或者其它的错误处理。
回复
恋喵大鲤鱼 2016-09-18
引用 28 楼 fefe82 的回复:
[quote=引用 25 楼 K346K346 的回复:] [quote=引用 19 楼 fefe82 的回复:] 析构函数的调用是一个对象生命结束的标志。 一旦析构函数返回,对对象的任何操作,包括访问任何成员变量,成员函数都不再合法。 使用析构函数的返回值报告错误,知道出错之后,能做些什么呢?
可以在出错之后,可以abort程序然后log,或者其它的错误处理。[/quote] 可以在析构函数内部进行 log 然后 throw ,基本就可以实现 log 然后 abort 。 throw 之后 catch 掉也可以交给其他错误处理。 不过在析构函数 throw 不是一个好习惯,经常会造成程序直接终止。当然如果程序终止是期望的行为就无所谓了 ... ================= 其他的错误处理能做什么呢?这个时候已经不能合法的访问被析构的对象和它的任何成员了。[/quote]您这么一说我又想起了,是不是因为C++的引入了完善的异常处理机制,所以就没有给析构函数设计有返回值,当然有一个原因就是析构函数一般情况下是由编译器自动调用,而非用户。基于上面这两点,所以C++标准未给析构函数设计有返回值。
回复
fefe82 2016-09-18
引用 25 楼 K346K346 的回复:
[quote=引用 19 楼 fefe82 的回复:] 析构函数的调用是一个对象生命结束的标志。 一旦析构函数返回,对对象的任何操作,包括访问任何成员变量,成员函数都不再合法。 使用析构函数的返回值报告错误,知道出错之后,能做些什么呢?
可以在出错之后,可以abort程序然后log,或者其它的错误处理。[/quote] 可以在析构函数内部进行 log 然后 throw ,基本就可以实现 log 然后 abort 。 throw 之后 catch 掉也可以交给其他错误处理。 不过在析构函数 throw 不是一个好习惯,经常会造成程序直接终止。当然如果程序终止是期望的行为就无所谓了 ... ================= 其他的错误处理能做什么呢?这个时候已经不能合法的访问被析构的对象和它的任何成员了。
回复
fefe82 2016-09-18
引用 24 楼 K346K346 的回复:
[quote=引用 20 楼 fefe82 的回复:] 析构函数不是一个普通的函数,除了它的函数体之外,它还要执行许多其他的操作,包括,调用它的成员的析构函数,调用它的基类的析构函数,等。 所以,析构函数中的 return 并不会直接返回调用者。 在这一过程中有很多析构函数被(隐式)调用了,最终的返回值又如何确定?
“析构函数中的 return 并不会直接返回调用者”,这句话您确定吗?我们可以显示调用析构函数来释放placement new构造的对象,在这种情况下不就是直接返回给用户了吗?[/quote] 不管是显示还是隐式调用,析构函数都是一样的,都不一定直接返回调用者,而是要先去析构成员和基类。 正因为如此它才是一个特殊的函数。 控制权回到析构函数的调用者的时候,所有的析构都已经结束。 12.4 Destructors 8 After executing the body of the destructor and destroying any automatic objects allocated within the body, a destructor for class X calls the destructors for X’s direct non-variant non-static data members, the destructors for X’s direct base classes and, if X is the type of the most derived class (12.6.2), its destructor calls the destructors for X’s virtual base classes. All destructors are called as if they were referenced with a qualified name, that is, ignoring any possible virtual overriding destructors in more derived classes. Bases and members are destroyed in the reverse order of the completion of their constructor (see 12.6.2). A return statement (6.6.3) in a destructor might not directly return to the caller; before transferring control to the caller, the destructors for the members and bases are called. Destructors for elements of an array are called in reverse order of their construction (see 12.6).
回复
局部变量析构的时候如何获取返回值?
回复
恋喵大鲤鱼 2016-09-18
引用 30 楼 akirya 的回复:
[quote=引用 29 楼 K346K346 的回复:]您这么一说我又想起了,是不是因为C++的引入了完善的异常处理机制,所以就没有给析构函数设计有返回值,当然有一个原因就是析构函数一般情况下是由编译器自动调用,而非用户。基于上面这两点,所以C++标准未给析构函数设计有返回值。
析构函数中不能抛异常[/quote]C++可以抛出异常,但最好不要抛出异常,确保安全的情况下可以抛出异常。
回复
C++的异常处理还完善?那VC++就不需要引入结构化异常处理了。
回复
paschen 版主 2016-09-18
http://blog.csdn.net/wind19/article/details/8213406
回复
引用 29 楼 K346K346 的回复:
您这么一说我又想起了,是不是因为C++的引入了完善的异常处理机制,所以就没有给析构函数设计有返回值,当然有一个原因就是析构函数一般情况下是由编译器自动调用,而非用户。基于上面这两点,所以C++标准未给析构函数设计有返回值。
析构函数中不能抛异常
回复
sweeterer 2016-09-17
这是基于大范围考虑的,this指针的类型根据撰写者定义而不同,要是给你定义返回值,那编译器还怎么判断this指针的类型
回复
恋喵大鲤鱼 2016-09-17
引用 20 楼 fefe82 的回复:
析构函数不是一个普通的函数,除了它的函数体之外,它还要执行许多其他的操作,包括,调用它的成员的析构函数,调用它的基类的析构函数,等。 所以,析构函数中的 return 并不会直接返回调用者。 在这一过程中有很多析构函数被(隐式)调用了,最终的返回值又如何确定?
“析构函数中的 return 并不会直接返回调用者”,这句话您确定吗?我们可以显示调用析构函数来释放placement new构造的对象,在这种情况下不就是直接返回给用户了吗?
回复
tiansk123 2016-09-17
构造函数和析构函数是两个非常特殊的函数:它们没有返回值.这与返回值为void的函数显然不同.后者虽然也不返回任何值,但还可以让它做点别的事情,而构造函数和析构函数则不允许.在程序中创建和消除一个对象的行为非常特殊,就像出生和死亡,而且总是由编译器来调用这些函数以确保它们被执行.如果它们有返回值,要么编译器必须知道如何处理返回值,要么就只能由客户程序员自己来显式的调用构造函数与析构函数,这样一来,安全性就被人破坏了.另外,析构函数不带任何参数,因为析构不需任何选项.
回复
tiansk123 2016-09-17
析构函数,没有必要有返回值,因为返回值不起作用,构造函数中的返回值,是他所构造的对象
回复
lm_whales 2016-09-16
释放资源,除了内存之外。还包括 包括关闭文件。释放各种句柄(Windows 有各种丰富的句柄) 总之,分配了资源,就要有个地方释放 析构函数,就是专门设计做这个任务的 异常是不能依赖返回值检测的 因为,一旦抛出异常,对应的函数,没有捕获异常 就没有机会顺次执行下去了 这样,也就不可能返回什么状态了。 抛出异常,然后捕获,作为函数返回值,这本身就不能算高效的。 在 析构函数中返回失败号码,是多余的。 Effective C++为何还会建议不要在析构函数中抛出异常,而是吞下异常。 是因为,有时候,人们会利用析构函数,做一些 析构函数分外的工作 C++ 并不阻止人们做这些 而且,有时候,有些库函数之类的,尤其是第三方库,可能会抛出异常 这些,都是不能保证,不会出现的 所以,有这个建议。
回复
fefe82 2016-09-16
析构函数不是一个普通的函数,除了它的函数体之外,它还要执行许多其他的操作,包括,调用它的成员的析构函数,调用它的基类的析构函数,等。 所以,析构函数中的 return 并不会直接返回调用者。 在这一过程中有很多析构函数被(隐式)调用了,最终的返回值又如何确定?
回复
fefe82 2016-09-16
析构函数的调用是一个对象生命结束的标志。 一旦析构函数返回,对对象的任何操作,包括访问任何成员变量,成员函数都不再合法。 使用析构函数的返回值报告错误,知道出错之后,能做些什么呢?
回复
ri_aje 2016-09-16
引用 8 楼 K346K346 的回复:
[quote=引用 5 楼 ri_aje 的回复:] 规定。 话说有的话你也用不上啊,析构函数都是编译器自动调用的。
为什么这样规定呢?是可以手动调用析构函数的![/quote] 析构过程都是先调用析构函数再释放空间,析构函数如果有返回值的话,也是出现在释放空间步骤的前面,编译器没法帮你保留到释放空间完成以后,然后再返回给你。
回复
发动态
发帖子
C++ 语言
创建于2007-09-28

5.9w+

社区成员

C++ 语言相关问题讨论,技术干货分享,前沿动态等
申请成为版主
社区公告
暂无公告