1. 概述类的析构函数执行与构造函数相反的操作当对象结束其生命周期程序就会自动执行析构函数1234567891011121314151617classImageEx{public:ImageEx(){cout Execute the constructor! endl;}~ImageEx(){cout Execute the destructor! endl;}};intmain(){ImageEx imageEx;return0;}那么同样的问题来了为什么要有析构函数呢2. 详论2.1. 对象生命周期在经典C中需要通过new/delete来手动管理动态内存。如果我们在类中申请一个动态数组并且通过自定义的函数Release()来释放它12345678910111213141516171819202122232425262728classImageEx{public:ImageEx(){cout Execute the constructor! endl;data newunsignedchar[10];}~ImageEx(){cout Execute the destructor! endl;}voidRelease(){delete[] data;data nullptr;}private:unsignedchar* data;};intmain(){{ImageEx imageEx;imageEx.Release();}return0;}那么当类对象离开作用域结束生命周期之前就必须显示调用一次成员函数Release()否则就会造成内存泄漏对象在调用析构函数之后只会销毁数据成员data本身而不是其指向的内存。那么一个合理的实现是将成员函数Release()放入到析构函数12345678910111213141516171819202122232425262728classImageEx{public:ImageEx(){cout Execute the constructor! endl;data newunsignedchar[10];}~ImageEx(){Release();cout Execute the destructor! endl;}private:unsignedchar* data;voidRelease(){delete[] data;data nullptr;}};intmain(){{ImageEx imageEx;}return0;}这样当类对象离开作用域结束生命周期之前就自动通过析构函数实现了动态数组的释放。好处是显而易见的实现了类似于内置数据类型对象的生命周期管理我们可以像使用内置数据类型对象一样使用类对象。2.2. 不一定需要显式析构在一些现代高级编程语言(C#、Java、Javascript)中已经不用去手动管理动态内存取而代之的是其与操作系统的中间件.netjvm浏览器的GC垃圾回收机制。而在现代C中提倡通过智能指针std::shared_ptr、std::unique_ptr、std::weak_ptr来管理动态内存对于动态数组则使用标准容器std::vector则更好。在两者的内部都实现了前文提到的对象生命周期管理在离开作用域后通过析构函数自动释放管理的内存无需再手动进行回收。那么一个显而易见的推论就出来了如果我们在类中使用智能指针或者vector容器来替代new/delete管理动态内存是不是就可以不用析构函数了?严格来说是不用显式使用析构函数12345678910111213141516classImageEx{public:ImageEx():data(10){cout Execute the constructor! endl;}private:std::vectorunsignedchar data;};intmain(){ImageEx imageEx;return0;}实际上并不是这个类不存在析构函数而是编译器会为它生成一个合成的析构函数在这个析构函数体中什么也不用做。因为类中的动态内存已经交由std::vector容器来管理。当类对象离开作用域调用析构函数之后会销毁这个std::vector容器数据成员进而触发其析构函数释放其管理的内存。2.3. 析构的必要性根据上一节内容不一定需要显式析构。因为现代C的一些机制能够帮你自动管理动态内存。但是析构函数还是必要的这是由于C语言本身的性质决定的。作为C语言大部分内容的超集需要兼容C语言手动管理内存的特性。更重要的是现代操作系统几乎全部由C语言编写与底层的交互不可避免的需要手动使用动态内存管理。3. 总结所以我们就能理解了C这门语言的设计哲学就是就是这样既想要C语言的高性能也想要高级语言高度抽象的特性。如果我们必须兼容C语言底层设计那我们最好使用析构函数释放动态内存否则多数情况下我们应该使用智能指针或者stl容器来管理动态内存从而避免显示使用析构函数。
C++面向对象编程之析构详解
发布时间:2026/7/14 6:24:54
1. 概述类的析构函数执行与构造函数相反的操作当对象结束其生命周期程序就会自动执行析构函数1234567891011121314151617classImageEx{public:ImageEx(){cout Execute the constructor! endl;}~ImageEx(){cout Execute the destructor! endl;}};intmain(){ImageEx imageEx;return0;}那么同样的问题来了为什么要有析构函数呢2. 详论2.1. 对象生命周期在经典C中需要通过new/delete来手动管理动态内存。如果我们在类中申请一个动态数组并且通过自定义的函数Release()来释放它12345678910111213141516171819202122232425262728classImageEx{public:ImageEx(){cout Execute the constructor! endl;data newunsignedchar[10];}~ImageEx(){cout Execute the destructor! endl;}voidRelease(){delete[] data;data nullptr;}private:unsignedchar* data;};intmain(){{ImageEx imageEx;imageEx.Release();}return0;}那么当类对象离开作用域结束生命周期之前就必须显示调用一次成员函数Release()否则就会造成内存泄漏对象在调用析构函数之后只会销毁数据成员data本身而不是其指向的内存。那么一个合理的实现是将成员函数Release()放入到析构函数12345678910111213141516171819202122232425262728classImageEx{public:ImageEx(){cout Execute the constructor! endl;data newunsignedchar[10];}~ImageEx(){Release();cout Execute the destructor! endl;}private:unsignedchar* data;voidRelease(){delete[] data;data nullptr;}};intmain(){{ImageEx imageEx;}return0;}这样当类对象离开作用域结束生命周期之前就自动通过析构函数实现了动态数组的释放。好处是显而易见的实现了类似于内置数据类型对象的生命周期管理我们可以像使用内置数据类型对象一样使用类对象。2.2. 不一定需要显式析构在一些现代高级编程语言(C#、Java、Javascript)中已经不用去手动管理动态内存取而代之的是其与操作系统的中间件.netjvm浏览器的GC垃圾回收机制。而在现代C中提倡通过智能指针std::shared_ptr、std::unique_ptr、std::weak_ptr来管理动态内存对于动态数组则使用标准容器std::vector则更好。在两者的内部都实现了前文提到的对象生命周期管理在离开作用域后通过析构函数自动释放管理的内存无需再手动进行回收。那么一个显而易见的推论就出来了如果我们在类中使用智能指针或者vector容器来替代new/delete管理动态内存是不是就可以不用析构函数了?严格来说是不用显式使用析构函数12345678910111213141516classImageEx{public:ImageEx():data(10){cout Execute the constructor! endl;}private:std::vectorunsignedchar data;};intmain(){ImageEx imageEx;return0;}实际上并不是这个类不存在析构函数而是编译器会为它生成一个合成的析构函数在这个析构函数体中什么也不用做。因为类中的动态内存已经交由std::vector容器来管理。当类对象离开作用域调用析构函数之后会销毁这个std::vector容器数据成员进而触发其析构函数释放其管理的内存。2.3. 析构的必要性根据上一节内容不一定需要显式析构。因为现代C的一些机制能够帮你自动管理动态内存。但是析构函数还是必要的这是由于C语言本身的性质决定的。作为C语言大部分内容的超集需要兼容C语言手动管理内存的特性。更重要的是现代操作系统几乎全部由C语言编写与底层的交互不可避免的需要手动使用动态内存管理。3. 总结所以我们就能理解了C这门语言的设计哲学就是就是这样既想要C语言的高性能也想要高级语言高度抽象的特性。如果我们必须兼容C语言底层设计那我们最好使用析构函数释放动态内存否则多数情况下我们应该使用智能指针或者stl容器来管理动态内存从而避免显示使用析构函数。