编译器创建析构函数

SmallCoder1992 2016-04-18 01:23:38
首先将我的几个问题提出来吧,如下:

(1). 编译器是否一定会为你生成析构函数?
(2).如果按照下面百度的说法,编译器不管你自己是否编写析构函数,它都会给你生成一个析构函数,但是什么也不做,那我就好奇了,什么都不做那生成出来干嘛?这是吃饱了撑了?还是有其他目的?
(3).今天我看深入探索c++对象模型的时候,书上是这么说的:如果用户没有定义析构函数,而且你类中的数据成员也没有定义析构函数,那么编译器是不会给你生成析构函数的,这和百度的解释不就出现矛盾了?这时候我该相信谁?问题是我没有办法去测试到底我该信谁(我只是想更好的了解c++的性质,是不是有点太多虑了?请不要见怪)
(4)今天我测试了一下下面这样一个案例
class Base
{
};

class Derived
{
public:
~Derived(){}
};

for(int i = 0; i != 10000000; ++i)
{
Base base;//或者 Derived derived;
}
然后我分别创建这两个对象10000000次,对比时间发现后者是前者的10倍左右,面对这个问题,我想知道的是这样一个简单的析构到底做了什么?
(5). 那么除了继承的需要和动态内存分配时候的delete的需要,那么是否一般的类型就没必要写析构了?毕竟我只是简单加了一个析构函数而已,而且我类中还没有数据成员,他就有这么大的性能区别,那么如何能很好的写好一个类?后来我又测试了一下,我在类中添加两个double类型的数据成员之后,发现这倍数又涨到将近30倍,所以自己发现想写好一个类都不是那么简单啊!

还请各位大神能给我指点,我只想把知识学的透点,掌握本质才好!

...全文
241 8 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
8 条回复
切换为时间正序
请发表友善的回复…
发表回复
赵4老师 2016-04-18
  • 打赏
  • 举报
回复
理解讨论之前请先学会如何观察! 计算机组成原理→DOS命令→汇编语言→C语言(不包括C++)、代码书写规范→数据结构、编译原理、操作系统→计算机网络、数据库原理、正则表达式→其它语言(包括C++)、架构…… 对学习编程者的忠告: 多用小脑和手,少用大脑、眼睛和嘴,会更快地学会编程! 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步Debug版对应汇编一行! 单步Debug版对应汇编千行不如单步Release版对应汇编一行! 不会单步Release版对应汇编?在你想单步Release版C/C++代码片断的前面临时加一句DebugBreak();重建所有,然后在IDE中运行。(一般人我不告诉他!单步类的实例“构造”或“复制”或“作为函数参数”或“作为函数返回值返回”或“参加各种运算”或“退出作用域”的语句对应的汇编代码几步后,就会来到该类的“构造函数”或“复制构造函数”或“运算符重载”或“析构函数”对应的C/C++源代码处。 VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。 不要迷信书、考题、老师、回帖; 要迷信CPU、编译器、调试器、运行结果。 并请结合“盲人摸太阳”和“驾船出海时一定只带一个指南针。”加以理解。 任何理论、权威、传说、真理、标准、解释、想象、知识……都比不上摆在眼前的事实! 有人说一套做一套,你相信他说的还是相信他做的? 其实严格来说这个世界上古往今来所有人都是说一套做一套,不是吗? 不要写连自己也预测不了结果的代码!
renwotao2009 2016-04-18
  • 打赏
  • 举报
回复
第五个问题,如果类中都是基本类型可以不用写析构,但如果你构造中初始化资源比如new了某个资源对象,你得在自定义析构中delete该资源。你类中增加成员数据,在栈中或堆(使用new)生成对象,那么它们都要分配空间,这些操作都要花费时间,建议你反汇编这些代码看看
fefe82 2016-04-18
  • 打赏
  • 举报
回复
首先,C++ 的语义与编译器的实现是不同的。 编译器实现只要保证在“可见的效果”上,与完全按照 C++ 语义完全一致即可。编译器如何做,属于编译器的实现细节。这与不同的CPU/OS/编译器/编译选项均有关。 比如:i=i+1; i=i-2; 语义上是一次加法,一次减法。但是编译器完全可以把它实现为 i = i - 1; (只进行一次减法),只要在"可见的效果“上,与两次加法效果相同。 [ 本部分仅为提示: 在某些极端情况(CPU, OS, 编译器)下两者效果可能不同。比如,如果 i 是有符号整数且有符号整数加法溢出会引起异常,那么 i= i + 1; i = i -2 ; 与 i = i - 1; 的“可见的效果" 会不同: i = i + 1; i = i - 2 可能因为溢出而引起异常(i = i + 1 溢出) ,而此时 i = i - 1; 可能不会引起异常。“可见的效果”之一,异常,不同。 另一方面,由于浮点计算误差的存在,i = i + 1; i = i - 2; 与 i = i - 1; 在 i 为浮点数时,结果可能有微小的差异。此时,由于“可见的效果" (i 的值)不同,因而编译不能进行这种转换。(所以 gcc 实际默认是不对浮点运算进行任何优化的,因为这几乎一定会影响“可见的效果”,除非编译的时候提供显式的编译选项允许这种优化)]
引用 楼主 u010222864 的回复:
(1). 编译器是否一定会为你生成析构函数?
在 C++ 的语义上,是的。 但是由于这个析构函数有时什么也不做,所以编译可能并不实际生成这样一个函数。
引用
(2).如果按照下面百度的说法,编译器不管你自己是否编写析构函数,它都会给你生成一个析构函数,但是什么也不做,那我就好奇了,什么都不做那生成出来干嘛?这是吃饱了撑了?还是有其他目的?
一个类,必须有构造函数和析构函数。这会使得定义 C++ 语言简单很多。 一种语言必须有它的形式化的定义,这样才能确定由这种语言书写的程序的行为。 构造函数和析构函数是 C++ 语言中类的基本特征,不管是什么样的类,这两个函数必须存在。
引用
(3).今天我看深入探索c++对象模型的时候,书上是这么说的:如果用户没有定义析构函数,而且你类中的数据成员也没有定义析构函数,那么编译器是不会给你生成析构函数的,这和百度的解释不就出现矛盾了?这时候我该相信谁?问题是我没有办法去测试到底我该信谁(我只是想更好的了解c++的性质,是不是有点太多虑了?请不要见怪)
析构函数在语义上必须存在。 但是当它什么也不做的时候,编译是否实际生成这个函数与/或时候实际调用这个函数并不影响”可见的效果“。所以编译器可以选择不生成/调用这个函数。这属于编译器的实现细节
引用
(4)今天我测试了一下下面这样一个案例 class Base { }; class Derived { public: ~Derived(){} }; for(int i = 0; i != 10000000; ++i) { Base base;//或者 Derived derived; } 然后我分别创建这两个对象10000000次,对比时间发现后者是前者的10倍左右,面对这个问题,我想知道的是这样一个简单的析构到底做了什么?
什么都不做,单单调用和返回也是需要时间的。
引用
(5). 那么除了继承的需要和动态内存分配时候的delete的需要,那么是否一般的类型就没必要写析构了?毕竟我只是简单加了一个析构函数而已,而且我类中还没有数据成员,他就有这么大的性能区别,那么如何能很好的写好一个类?后来我又测试了一下,我在类中添加两个double类型的数据成员之后,发现这倍数又涨到将近30倍,所以自己发现想写好一个类都不是那么简单啊! 还请各位大神能给我指点,我只想把知识学的透点,掌握本质才好!
性能问题,等你遇到了之后再去解决。请相信现代编译器能够解决 99% 的性能优化问题(当然可能需要设置相应的优化选项)。每个实际问题遇到的实际的性能问题都必须单独寻找解决方案。通用的性能问题请相信你通常不能比编译器做得更好。 ------------------------- 最好,还请注意区分 C++ 本身的语义 与 编译器实现细节的不同。 编译器的实现细节可能对不同的编译器、编译选项、CPU、OS都会不同。C++ 本身的语义则是由一个国际标准所规定的(ISO/IEC 14882)。
renwotao2009 2016-04-18
  • 打赏
  • 举报
回复
第四个问题,可以看看代码的汇编代码,构造析构函数它们都是函数调用,子类对象多了一次父类对象的构造和析构函数调用,自然要花费时间,函数调用也要执行代码的
renwotao2009 2016-04-18
  • 打赏
  • 举报
回复
第三个问题析构函数如果你没去定义编译器给你生成一个,没有见过百度上解释的那样,只有一个析构函数。编译器生成的默认析构什么也不做但自定义的可能要释放资源等,但调用子类对象析构时,不管是默认析构还是自定义析构都调用父类析构
renwotao2009 2016-04-18
  • 打赏
  • 举报
回复
第一个问题,析构函数你自己这颗就不生成默认的 第二个问题即使析构函数什么也不做,他也要被调用,这首先保证语义完整,有构造有析构,而大多数情况析构是有用的,构造函数初始化的资源,在析构函数中释放
SmallCoder1992 2016-04-18
  • 打赏
  • 举报
回复
引用 5 楼 renwotao2009 的回复:
第五个问题,如果类中都是基本类型可以不用写析构,但如果你构造中初始化资源比如new了某个资源对象,你得在自定义析构中delete该资源。你类中增加成员数据,在栈中或堆(使用new)生成对象,那么它们都要分配空间,这些操作都要花费时间,建议你反汇编这些代码看看
额!目前还没有接触汇编语言!
SmallCoder1992 2016-04-18
  • 打赏
  • 举报
回复
引用 4 楼 fefe82 的回复:
首先,C++ 的语义与编译器的实现是不同的。 编译器实现只要保证在“可见的效果”上,与完全按照 C++ 语义完全一致即可。编译器如何做,属于编译器的实现细节。这与不同的CPU/OS/编译器/编译选项均有关。 比如:i=i+1; i=i-2; 语义上是一次加法,一次减法。但是编译器完全可以把它实现为 i = i - 1; (只进行一次减法),只要在"可见的效果“上,与两次加法效果相同。 [ 本部分仅为提示: 在某些极端情况(CPU, OS, 编译器)下两者效果可能不同。比如,如果 i 是有符号整数且有符号整数加法溢出会引起异常,那么 i= i + 1; i = i -2 ; 与 i = i - 1; 的“可见的效果" 会不同: i = i + 1; i = i - 2 可能因为溢出而引起异常(i = i + 1 溢出) ,而此时 i = i - 1; 可能不会引起异常。“可见的效果”之一,异常,不同。 另一方面,由于浮点计算误差的存在,i = i + 1; i = i - 2; 与 i = i - 1; 在 i 为浮点数时,结果可能有微小的差异。此时,由于“可见的效果" (i 的值)不同,因而编译不能进行这种转换。(所以 gcc 实际默认是不对浮点运算进行任何优化的,因为这几乎一定会影响“可见的效果”,除非编译的时候提供显式的编译选项允许这种优化)] [quote=引用 楼主 u010222864 的回复:] (1). 编译器是否一定会为你生成析构函数?
在 C++ 的语义上,是的。 但是由于这个析构函数有时什么也不做,所以编译可能并不实际生成这样一个函数。
引用
(2).如果按照下面百度的说法,编译器不管你自己是否编写析构函数,它都会给你生成一个析构函数,但是什么也不做,那我就好奇了,什么都不做那生成出来干嘛?这是吃饱了撑了?还是有其他目的?
一个类,必须有构造函数和析构函数。这会使得定义 C++ 语言简单很多。 一种语言必须有它的形式化的定义,这样才能确定由这种语言书写的程序的行为。 构造函数和析构函数是 C++ 语言中类的基本特征,不管是什么样的类,这两个函数必须存在。
引用
(3).今天我看深入探索c++对象模型的时候,书上是这么说的:如果用户没有定义析构函数,而且你类中的数据成员也没有定义析构函数,那么编译器是不会给你生成析构函数的,这和百度的解释不就出现矛盾了?这时候我该相信谁?问题是我没有办法去测试到底我该信谁(我只是想更好的了解c++的性质,是不是有点太多虑了?请不要见怪)
析构函数在语义上必须存在。 但是当它什么也不做的时候,编译是否实际生成这个函数与/或时候实际调用这个函数并不影响”可见的效果“。所以编译器可以选择不生成/调用这个函数。这属于编译器的实现细节
引用
(4)今天我测试了一下下面这样一个案例 class Base { }; class Derived { public: ~Derived(){} }; for(int i = 0; i != 10000000; ++i) { Base base;//或者 Derived derived; } 然后我分别创建这两个对象10000000次,对比时间发现后者是前者的10倍左右,面对这个问题,我想知道的是这样一个简单的析构到底做了什么?
什么都不做,单单调用和返回也是需要时间的。
引用
(5). 那么除了继承的需要和动态内存分配时候的delete的需要,那么是否一般的类型就没必要写析构了?毕竟我只是简单加了一个析构函数而已,而且我类中还没有数据成员,他就有这么大的性能区别,那么如何能很好的写好一个类?后来我又测试了一下,我在类中添加两个double类型的数据成员之后,发现这倍数又涨到将近30倍,所以自己发现想写好一个类都不是那么简单啊! 还请各位大神能给我指点,我只想把知识学的透点,掌握本质才好!
性能问题,等你遇到了之后再去解决。请相信现代编译器能够解决 99% 的性能优化问题(当然可能需要设置相应的优化选项)。每个实际问题遇到的实际的性能问题都必须单独寻找解决方案。通用的性能问题请相信你通常不能比编译器做得更好。 ------------------------- 最好,还请注意区分 C++ 本身的语义 与 编译器实现细节的不同。 编译器的实现细节可能对不同的编译器、编译选项、CPU、OS都会不同。C++ 本身的语义则是由一个国际标准所规定的(ISO/IEC 14882)。[/quote] 好的,谢谢!

65,186

社区成员

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

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