首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

【C++】多态 ⑤ ( 虚析构函数 | 虚析构函数语法 | 虚析构函数意义 | 父类指针指向子类对象情况下父类和子类使用 virtual 虚析构函数 | 代码示例 )

A 的构造函数 , 然后调用 B 的构造函数 , 最后调用 C 的构造函数 ; 参考 【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 ) 博客中 , 构造函数..., 则编译器会自动生成一个 析构函数 , 该 析构函数 会首先调用 父类 的 析构函数 , 然后执行 子类 的 析构函数 ; 使用 虚析构函数 的目的是 确保在释放 子类 对象时正确地释放资源和调用析构函数...; 当使用 父类 指针指向一个 子类 对象时 , 如果要通过 delete 释放该指针指向的对象 , 如果是正常的析构函数 , 没有 使用 virtual 定义虚析构函数 , 则只会调用 父类 的 析构函数..., 子类的析构函数不会被调用到 ; 虚析构函数 可以确保 首先调用 子类 的 析构函数 , 然后调用 父类 的析构函数 ; 这样可以 避免在 释放 子类对象 时出现 资源泄漏 的情况 ; 需要注意的是...虚析构函数 1、代码示例 - 没有使用虚析构函数导致子类析构函数无法调用 在下面的代码中 , 声明 子类指针 指向 子类对象 , 释放 子类指针 时 先调用 子类析构函数 , 再调用父类析构函数 ; 声明

1.4K20

C++编程经验(4):不要在构造函数和析构函数中使用虚函数

---- 构造函数中调用虚函数 首先构造函数中不能调用虚函数,不是说语法不允许,最重要的原因在于,当有继承的时候,父类会调用到子类的函数,但是此时子类并没有初始化,会导致数据错误,就这一点足已让你不能在构造函数中调用虚函数...~A() { cout 析构函数"; cout << "A::Test()" << endl; } virtual void Test() { cout 析构函数"; Test(); } virtual void Test() { cout << "B::Test()" << endl; } }; int main() {...---- 析构函数中调用虚函数 在对象的析构期间,存在与上面同样的逻辑。一旦一个派生类的析构器运行起来,该对象的派生类数据成员就被假设为是未定义的值,这样以来,C++就把它们当做是不存在一样。...一旦进入到基类的析构器中,该对象即变为一个基类对象,C++中各个部分(虚函数,dynamic_cast运算符等等)都这样处理。

1.7K30
  • 您找到你想要的搜索结果了吗?
    是的
    没有找到

    通过C++编译视频平台为什么要使用virtual虚析构函数?

    比如在编译中,我们使用了C++语言,为了在对象不被使用之后释放资源,虚函数也可实现多态,我们将虚函数加上了virtual。 C++中基类的析构函数为什么要用virtual虚析构函数?...我们先来看两段代码的运行结果对比下: 代码1: image.png 代码2: image.png 运行函数: image.png 执行代码1运行结果: image.png 执行代码2运行结果: image.png...因此,MyClass类的析构函数并没有被调用,但是正常情况下析构函数里都会释放各种资源,而析构函数不被调用的话就会导致内存泄漏。...代码1加上virtual关键字,运行次代码会调用析构函数,避免内存泄漏。 所以c++中基类采用virtual虚析构函数主要是为了防止内存泄漏。如果派生类中申请内存空间,而且在析构函数中对内存进行释放。...如果没有采用虚构函数,而释放该类对象,派生类对象就不会得到动态绑定。这种情况就会导致内存泄漏。所以为了防止内存泄漏,只要继承关系,被继承的类析构函数是虚函数,都会加上virtual关键字。

    54920

    【C++】匿名对象 ③ ( 函数返回值为对象值时 匿名对象 的 拷贝构造函数 与 析构函数 调用情况分析 )

    , 以及不同的使用场景下 , 匿名对象 的 创建与销毁情况 ; C++ 编译器 发现 使用 匿名对象 时 , 会根据 匿名对象 的用法 , 决定对 匿名对象的 处理 ; 匿名对象单独使用 : 如果只是单纯的使用...// 使用 函数返回匿名对象 初始化变量 Student s = fun(); 执行结果如下 : 调用带参数构造函数 m_age = 12 调用拷贝构造函数 调用析构函数 : m_age = 12 学生信息...fun 函数中 , 函数返回对象值时 , 创建 要返回的 普通对象副本 , 也就是一个 匿名对象 ; 调用析构函数 : m_age = 12 这是 fun 函数执行完毕 , 在函数作用域中的 普通对象...匿名对象 ; 调用析构函数 : m_age = 12 这是 fun 函数执行完毕 , 在函数作用域中的 普通对象 需要被析构销毁 ; 调用析构函数 : m_age = 12 这是在 main 函数中..., 使用 匿名对象 为 普通变量赋值 , 需要将 匿名对象的值赋值给普通对象 , 匿名对象 之后直接销毁 , 这是调用析构函数 销毁 fun 函数返回的匿名对象 ; 学生信息 : 年龄 = 12 , 身高

    33920

    【C++】探索C++内存管理:机制揭秘与内存安全

    然后,malloc函数会搜索内存堆的空闲链表(free list)来找到适合大小的空闲块。空闲链表是一组已经被释放的内存块,被组织成链表结构以便快速查找。...A; 可以自动调用它的构造函数进行初始化; 相应的对于delete释放空间时: delete p2; 也会自动调用它的析构函数并释放空间; 如下图所示: new/delete 和 malloc.../free最大区别是 new/delete对于自定义类型除了开空间还会调用构造函数和析构函数;而对于内置类型是几乎是一样的; ✨当然对于开辟多个对象也会自动多次调用构造函数和析构函数,例如: #include...,new不需要,但是new需要捕获异常 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理...内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费。

    15410

    【cc++】深入探秘:C++内存管理的机制

    这种方式更简洁,也更安全,因为它保证了对象在使用前被正确初始化,注意这里ListNode是自定义类型,除了开空间还会调用构造函数 只要我们写好构造函数,我们发现new的使用是十分方便的 我们来构建一个链表...这是因为在执行 delete[] p2; 时,系统需要知道要调用多少次析构函数 让我们具体看一下为什么会这样: 对象数组的内存分配:当你创建一个对象数组时,例如 new A[10],C++ 需要知道在稍后释放数组时应该调用多少次析构函数...为此,它可能在分配给数组的内存块中存储一些额外的元数据,通常是数组的长度 析构函数调用:在使用 delete[] p2; 释放内存时,这个额外存储的信息就被用来确保为数组中的每个元素正确调用析构函数...,new不需要,但是new需要捕获异常 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理...假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak 系统资源泄漏 指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉

    27710

    初识C++ · 内存管理

    为什么说new用来手搓链表就很爽,因为我们不用没开辟一个就去assert一下,new里面的抛异常会帮我们解决; 因为抛异常是后面的知识了,这里简单介绍,在C语言中报错是通过返回错误码,比较暴力,在C++...3.2 delete 同C语言,开辟了空间,使用完就要还给操作系统,C语言中使用的是free,在C++中使用的是delete,delete = operator delete+ 析构,而operator...当我们显式调用了析构函数之后,真的只开辟了80个字节吗?...在2019中,我们进入到operator new中就可以看到: 我们明明只要40个字节,却多开了4个字节,但是当我们注释掉析构函数之后,我们再去调试,就会发现size变成了40,也就是有没有显式调用析构函数会影响实际开辟的空间大小...: 其中的缘由就是多开的4个空间是用来干嘛的,当显式调用析构函数之后,多开辟的空间就是用来记录有多少个空间需要被析构,是一个数字用来记录,那么就多开了一个整型,所以会多4字节,如果没有显式调用析构就不会

    6210

    你们要的C++面试题答案来了--基础篇

    pa ,pb之间互相引用,两个资源的引用计数为2,当要跳出函数时,智能指针pa,pb析构时两个资源引用计数会减一,但是两者引用计数还是为1,导致跳出函数时资源没有被释放(A B的析构函数没有被调用),如果把其中一个改为...为什么C++默认的析构函数不是虚函数 考点:虚函数 析构函数 参考回答: 将可能会被继承的父类的析构函数设置为虚函数,可以保证当我们new一个子类,然后使用基类指针指向该子类对象,释放基类指针时可以释放掉子类的空间...C++默认的析构函数不是虚函数是因为虚函数需要额外的虚函数表和虚表指针,占用额外的内存。而对于不会被继承的类来说,其析构函数如果是虚函数,就会浪费内存。...因此C++默认的析构函数不是虚函数,而是只有当需要当作父类时,设置为虚函数。...,如对象所在的函数已调用完毕时,系统会自动执行析构函数。

    2.9K31

    嵌入式面试高频考点整理(建议收藏)

    C++中内存泄漏的几种情况[17] 在类的构造函数和析构函数中没有匹配的调用new和delete函数 没有正确地清除嵌套的对象指针 在释放对象数组时在delete中没有使用方括号 指向对象的指针数组不等同于对象数组...「析构函数顺序」: 派生类本身的析构函数、对象成员析构函数、基类析构函数(与构造顺序正好相反)。 用 C++设计一个不能被继承的类 将自身构造函数和析构函数声明为private。...,还没有内存空间,更没有虚函数表地址用来调用虚函数即构造函数了 析构函数最好声明为虚函数 首先析构函数可以为虚函数,当析构一个指向派生类的基类指针时,最好将基类的析构函数声明为虚函数,否则可以存在内存泄露的问题...如果析构函数不被声明成虚函数,则编译器实施静态绑定,在删除指向派生类的基类指针时,只会调用基类的析构函数而不调用派生类析构函数,这样就会造成派生类对象析构不完全。...提高c++性能,你用过哪些方式去提升[26] 空间足够时,可以将经常需要读取的资源,缓存在内存中。 尽量减少大内存对象的构造与析构,考虑缓存暂时不用的对象,等待后续继续使用。

    75620

    CC++内存管理及内存泄漏详解

    栈区主要存放运行函数而分配的局部变量、函数参数、返回数据、返回地址等。 堆区(heap):⼀般由程序员分配释放,若程序员不释放,程序结束时可能由OS(操作系统)回收。分配方式类似于链表。...: delete和free的对比: 注意:在申请自定义类型的空间时,new会调用构造函数,delete会调用析构函数,而malloc与 free不会。...我们在使用malloc时,常常需要进行如下的类型检查,防止内存开辟失败: struct Node { int val; Node* next; }; //以创建一个链表的节点为例 Node* CreateNode...在申请的空间上执行构造函数,完成对象的构造 delete的原理 在空间上执行析构函数,完成对象中资源的清理工作 调用operator delete函数释放对象的空间 new T[N]的原理 调用operator...new[]函数,在operator new[]中实际调用operator new函数完成N个对象空间的申请 在申请的空间上执行N次构造函数 delete[]的原理 在释放的对象空间上执行N次析构函数,

    15110

    【C++ 初阶路】--- C++内存管理

    二、C++内存管理方式 C语言内存管理方式在C++中可以继续使用,但有些地方就无能为力,而且使用起来比较麻烦,因此C++又提出了自己的内存管理方式:通过new和delete操作符 进行动态内存管理。...(基于编译器的优化) new和delete不匹配问题: 一个非常典型的问题(基于编译器的优化)就是:当new多个自定类型时(A* p = new A[10]),且直接使用delete A,如果A类显示实现析构函数就会报错...,如果不写析构函数就不会报错!...而不实现析构函数,就不会多开辟空间,也就避免了这样的问题。当然两者情况都可能会导致内存泄漏的问题!: 所以new和delete一定要匹配使用,因为导致的结果可能是不确定的!...可以先创建一个哨兵位(MyList head(-1);,栈上开辟,此节点为了方便后续链表节点的链接,且在创建单链表函数结束时自动销毁);然后通过cin输入链表节点值(val),并在堆上开辟链表节点(new

    8310

    【C++初阶】C++内存管理

    函数" << endl; } ~A() { cout 析构函数" << endl; } private: int _a; }; int main() { A* ptr1...+ 调用构造函数初始化 而operator new申请空间的底层实现也是调用malloc, 所以new的效率并没有比malloc高 封装malloc,申请内存失败,抛异常 封装malloc只是为了符合面向对象处理出现错误的处理方式...构造函数有点不一样,在我们之前学的都不能显式调用,但是定位new表达式就可以完成显式调用 ps:析构函数可以显式调用(下图证明) class A { public: A(int a = 10)...:_a(a) { cout 函数" << endl; } ~A() { cout 析构函数" << endl; } private: int _a; };...(想想永不关闭的程序,比如后台服务器就知道危害了) 内存泄漏指由于疏忽或者错误造成程序未能释放已经不再使用的内存的情况 并不是指物理上的消失,而是失去了对这段内存的控制,从而造成了内存的浪费

    86530

    【C++】42道面试经典问题总结

    而且提供了析构函数,那么用new[] 就一定要用delete[]ptr,不能够混用。 delete相对于free,1.调用析构函数2.释放内存 C++的static关键字的作用?...空间配置器allocator:给容器使用的,主要作用就是把内存开辟与对象构造分开,把对象析构和内存释放分离开。...当容器删除一个元素时不应该进行内存释放(后面可能会继续使用),只用把对象析构掉即可。 vector和list的区别? vector底层数据结构是数组,list底层数据结构是链表。...虚析构函数,把基类的析构函数实现成虚析构函数,则对析构函数的调用进行动态绑定,基类、派生类的析构函数就都可以调用到 构造函数和析构函数中能不能抛出异常?...deque的内存利用率比较好,刚开始就有一段内存可以提供使用 虚函数?

    12510

    C++初阶-CC++内存管理

    在申请的空间上执行构造函数,完成对象的构造 delete的原理 在空间上执行析构函数,完成对象中资源的清理工作 调用operator delete函数释放对象的空间 new...;//显示调用构造函数 //等价于使用 delete pt; pt->~Test();//显示调用析构函数 operator delete(pt); } 七、常见面试题 1、malloc...malloc申请空间失败时,返回的是NULL,因此使用时必须判空,new不需要,但是new需要捕获异常 申请自定义类型对象时,malloc/free只会开辟空间,不会调用构造函数与析构函数...,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中资源的清理 2、内存泄漏 什么是内存泄漏: 内存泄漏指因为疏忽或错误造成程序未能释放已经不再使用的内存的情况...内存泄漏并不是指内存在物理上的消失,而是应用程序分配某段内存后,因为设计错误,失去了对该段内存的控制,因而造成了内存的浪费 内存泄漏的危害: 长期运行的程序出现内存泄漏,影响很大,如操作系统、后台服务等等

    44820

    你踩过几种C++内存泄露的坑?

    这个我们就要注意了,一般当你构建一个类的时候,写析构函数一定要切记释放类成员关联的资源。...pArrayObjs 1~4并没有调用析构函数,从而导致其中的m_pStr指向的内存没有释放。所以我们要注意new和delete要匹配使用,当使用的new []申请的内存最好要用delete[]。...,那么在调用delete pObj;的时候会直接调用Father的析构函数,而不会调用Child的析构函数,这就导致了Child中的m_pStr所指向的内存,并没有被释放,从而导致了内存泄露。...并不是绝对,当有这种使用场景的时候,最好是设置基类的析构函数为虚析构函数。...那么在函数退出后,当pSecondNode调用析构函数的时候,对象的引用计数减一,引用计数为0,释放第二个Node,在释放第二个Node的过程中又调用了m_pPreNode的析构函数,第一个Node对象的引用计数减

    48650

    【CC++】图文题目吃透内存管理

    new会调用构造函数,delete会调用析构函数,而malloc与free不会 new调用构造函数和delete调用析构函数,这很大程度方便了我们,比如构造一个链表: struct ListNode {...2.自定义类型 new的原理 1.调用operator new函数申请空间 2.在申请的空间上执行构造函数,完成对象的构造 delete的原理 1.在空间上执行析构函数,完成对象中资源的清理工作...,不会调用构造函数和析构函数,而new在申请空间后会调用构造函数完成对象的初始化,delete在释放空间前会调用析构函数完成空间中的资源的清理。...内存泄漏是指因为疏忽或者错误造成程序未能释放已经不在使用的内存的情况,并不是指内存在物理上的丢失,而是应用程序分配某段内存后,因为设计错误,失去对该段内存的控制,因此造成了内存泄漏 内存泄漏的危害:...假设程序的设计错误导致这部分内存没有被释放,那么以后这部分空间将无法再被使用,就会产生Heap Leak 系统资源泄漏 指程序使用系统分配的资源,比方套接字、文件描述符、管道等没有使用对应的函数释放掉

    1K20

    你踩过几种C++内存泄露的坑?

    pArrayObjs 1~4并没有调用析构函数,从而导致其中的m_pStr指向的内存没有释放。所以我们要注意new和delete要匹配使用,当使用的new []申请的内存最好要用delete[]。...,那么在调用delete pObj;的时候会直接调用Father的析构函数,而不会调用Child的析构函数,这就导致了Child中的m_pStr所指向的内存,并没有被释放,从而导致了内存泄露。...并不是绝对,当有这种使用场景的时候,最好是设置基类的析构函数为虚析构函数。...还是之前那句话,如果通过手动去控制难免会出现遗漏的情况, C++提供了weak_ptr。...那么在函数退出后,当pSecondNode调用析构函数的时候,对象的引用计数减一,引用计数为0,释放第二个Node,在释放第二个Node的过程中又调用了m_pPreNode的析构函数,第一个Node对象的引用计数减

    1.5K20

    C++从入门到精通——C++动态内存管理

    另外,使用new时,还可以使用delete来释放分配的内存,并调用对象的析构函数进行清理。...而直接使用operator delete来释放内存,则需要自己手动调用对象的析构函数进行清理,没有自动调用析构函数的功能。...其次,我们在使用动态分配的内存时,要确保在使用完后及时释放内存,以免出现内存泄漏的问题。可以使用delete来释放动态分配的内存。...总结:自定义类型并不一定比内置类型多开几个字节,主要看存不存在析构函数,如果存在析构函数,使用free和delete是会报错,要使用delete[],因为delete[]底层会自动向前取几个字节 图片展示...malloc会出现自定义类型多开几个字节吗 在C语言中,使用malloc函数来动态分配内存时,分配的内存大小取决于所请求的字节数,与类型无关。

    21610

    CC++内存详解

    这些函数允许程序在运行时根据需要分配和释放内存,而不是在编译时静态地分配内存。这对于处理未知大小的数据或需要动态增长的数据结构(如链表、树等)特别有用。...C++动态内存申请 C语言的动态内存申请函数对于C++依旧可以使用。但也引入了新的动态内存申请方式:new、delete。...注意,对于数组,必须使用 delete[] 而不是 delete 来释放内存,以确保为每个元素调用析构函数(如果元素类型是类类型的话)。...因此,在使用 new 时,可能需要考虑异常处理。 对于基本数据类型(如 int、float 等),new 和 delete 主要用于分配和释放内存,不会调用任何特殊的构造函数或析构函数。...,delete对象的同时会调用析构函数对对象进行析构。

    10610

    【重学C++】01| C++ 如何进行内存资源管理?

    而且,这些问题可能不会立即出现,而是运行一段时间后,才会暴露出现,排查也很困难。因此,了解和掌握C++中的内存管理技巧和工具是非常重要的,可以提高程序性能、减少错误和增加安全性。...在程序运行期间,数据段的大小固定不变,但其内容可以被修改。按照变量是否被初始化。数据段可分为已初始化数据段和未初始化数据段。栈C++中函数调用以及函数内的局部变量的使用,都是通过栈这个内存分区实现的。...前面例子中的本地变量是简单类型,在C++中称为POD类型。对于带有构造和析构函数的非POD类型变量,栈上的内存分配同样有效。编译器会在合适的时机,插入对构造函数和析构函数的调用。...这里有个问题,当函数执行发生异常时,析构函数还会被调用吗?答案是会的,C++对于发生异常时对析构函数的调用称为"栈展开"。通过下面这段代码演示栈展开。...当AutoIntPtr超出作用域时,自动调用析构函数来释放所包含的资源。

    22500
    领券