鱼C论坛

 找回密码
 立即注册
查看: 2191|回复: 3

[已解决]求助路过的各位大佬(c++析构函数和栈区数据释放问题)

[复制链接]
发表于 2022-7-15 02:37:27 | 显示全部楼层 |阅读模式
60鱼币
c++中,栈区数据是由析构函数负责释放的吗?

        如果是,重写析构函数(如下),那A的对象调用析构函数后,栈区的数据可以不被释放了?

class A
{
public:
        int data;
        int* test;

private:
        A()
        {
                this->data = 10;
                test = new int(20);
        }

        ~A()
        {
                cout << "啥也不干" << endl;
        }
};

        如果不是,栈区的数据是由谁负责释放的呢?
最佳答案
2022-7-15 02:37:28
先说对具体这份代码的结论,为了辅助说明做了一个小测试,使用的代码如下
  1. #include<iostream>
  2. using namespace std;
  3. class A{
  4.   public:
  5.     int data;
  6.     int* test;
  7.     A(){
  8.         this->data = 10;
  9.         test = new int(20);
  10.     }
  11.     ~A(){
  12.         cout << "啥也不干" << endl;
  13.     }
  14. };
  15. int main(){
  16.     A a;
  17.     return 0;
  18. }
复制代码

这里像二楼所说的,需要将构造函数(和析构函数)声明为 public ,否则无法从外部调用无法通过编译。在编译中加入地址检查,运行结果得到(部分环境相关内容已经删减)
  1. 啥也不干

  2. =================================================================
  3. ==****==ERROR: LeakSanitizer: detected memory leaks

  4. Direct leak of 4 byte(s) in 1 object(s) allocated from:
  5.     #0 0x564dbfcacf52 in operator new(unsigned long)
  6.     #1 0x564dbfcafed9 in A::A() test.cpp:9:16
  7.     #2 0x564dbfcafed9 in main test.cpp:16:7
  8.     #3 0x7fada262928f  (libc.so.6)

  9. SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
复制代码

可见造成了内存泄漏,使用 new 运算符分配的空间没有得到释放。
析构函数提供了一个安排此类型对象的实例生命周期终止时执行的清理工作的位置,能确保不会由于忘记调用释放资源的方法而造成的资源泄漏。应该在析构函数中负责完成全生命周期中可能申请和持有的资源的合理释放等工作——如果在构造函数中申请分配空间,就应该在析构函数中进行释放;如果在工作过程中可能申请更多资源,就应该在析构函数中检查是否仍然持有,如果是则可能需要将其释放。总体上,程序编写者应该为自己的每一个 new 运算符负责,进行对应的释放操作,除非明确的将其交由其他组件进行管理和释放,一个比较典型的情形是一些库的设计中可能会申请一些空间使用并返回指针给调用者,要求调用者在合适的时间将其释放。
也推荐考虑在 C++ 中使用智能指针如 unique_ptr 来进行动态内存管理,正确使用可以显著的减小出现内存泄漏的可能性。

最佳答案

查看完整内容

先说对具体这份代码的结论,为了辅助说明做了一个小测试,使用的代码如下 这里像二楼所说的,需要将构造函数(和析构函数)声明为 public ,否则无法从外部调用无法通过编译。在编译中加入地址检查,运行结果得到(部分环境相关内容已经删减) 可见造成了内存泄漏,使用 new 运算符分配的空间没有得到释放。 析构函数提供了一个安排此类型对象的实例生命周期终止时执行的清理工作的位置,能确保不会由于忘记调用释放资源的 ...
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-7-15 02:37:28 | 显示全部楼层    本楼为最佳答案   
先说对具体这份代码的结论,为了辅助说明做了一个小测试,使用的代码如下
  1. #include<iostream>
  2. using namespace std;
  3. class A{
  4.   public:
  5.     int data;
  6.     int* test;
  7.     A(){
  8.         this->data = 10;
  9.         test = new int(20);
  10.     }
  11.     ~A(){
  12.         cout << "啥也不干" << endl;
  13.     }
  14. };
  15. int main(){
  16.     A a;
  17.     return 0;
  18. }
复制代码

这里像二楼所说的,需要将构造函数(和析构函数)声明为 public ,否则无法从外部调用无法通过编译。在编译中加入地址检查,运行结果得到(部分环境相关内容已经删减)
  1. 啥也不干

  2. =================================================================
  3. ==****==ERROR: LeakSanitizer: detected memory leaks

  4. Direct leak of 4 byte(s) in 1 object(s) allocated from:
  5.     #0 0x564dbfcacf52 in operator new(unsigned long)
  6.     #1 0x564dbfcafed9 in A::A() test.cpp:9:16
  7.     #2 0x564dbfcafed9 in main test.cpp:16:7
  8.     #3 0x7fada262928f  (libc.so.6)

  9. SUMMARY: AddressSanitizer: 4 byte(s) leaked in 1 allocation(s).
复制代码

可见造成了内存泄漏,使用 new 运算符分配的空间没有得到释放。
析构函数提供了一个安排此类型对象的实例生命周期终止时执行的清理工作的位置,能确保不会由于忘记调用释放资源的方法而造成的资源泄漏。应该在析构函数中负责完成全生命周期中可能申请和持有的资源的合理释放等工作——如果在构造函数中申请分配空间,就应该在析构函数中进行释放;如果在工作过程中可能申请更多资源,就应该在析构函数中检查是否仍然持有,如果是则可能需要将其释放。总体上,程序编写者应该为自己的每一个 new 运算符负责,进行对应的释放操作,除非明确的将其交由其他组件进行管理和释放,一个比较典型的情形是一些库的设计中可能会申请一些空间使用并返回指针给调用者,要求调用者在合适的时间将其释放。
也推荐考虑在 C++ 中使用智能指针如 unique_ptr 来进行动态内存管理,正确使用可以显著的减小出现内存泄漏的可能性。
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-7-15 08:31:07 | 显示全部楼层
你的代码中构造函数必须是 public 访问。数据可以是私有的。

有 new 必须要有 delete(如同:C语言的 malloc 和 free 一样),是一对的。必须养成写 delete 的习惯。
你的问题很简单啊,释放当然就是由电脑释放(如果你没有写 delete 的情况下,电脑会在 关闭 / 结束 代码后,自动释放内存,但这是不好习惯)
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

发表于 2022-7-15 08:34:01 | 显示全部楼层
都是析构时自己释放否则容易内存泄漏
养成好习惯
小甲鱼最新课程 -> https://ilovefishc.com
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2025-4-24 01:19

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表