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

为什么在这段代码中调用2次析构函数?

在这段代码中调用了两次析构函数的原因可能是由于对象的拷贝或移动操作导致的。

在C++中,当一个对象被拷贝或移动时,会调用相应的拷贝构造函数或移动构造函数来创建新的对象。而当一个对象的生命周期结束时,会调用析构函数来销毁对象并释放资源。

如果在代码中存在对象的拷贝或移动操作,可能会导致多次调用析构函数。以下是一些常见的情况:

  1. 对象的拷贝:当一个对象被赋值给另一个对象时,会调用拷贝构造函数来创建新的对象。在这个过程中,原对象的析构函数会被调用一次,新对象的析构函数也会被调用一次。
  2. 对象的移动:当一个对象被移动到另一个对象时,会调用移动构造函数来创建新的对象。在这个过程中,原对象的析构函数会被调用一次,新对象的析构函数也会被调用一次。
  3. 容器的操作:如果对象被存储在容器中,当容器销毁时,会调用容器中每个对象的析构函数。如果容器进行了拷贝或移动操作,也会导致多次调用析构函数。

需要注意的是,如果在代码中没有明确的拷贝或移动操作,而仍然出现了多次调用析构函数的情况,可能是由于浅拷贝或浅析构导致的。这种情况下,需要检查对象的拷贝构造函数和析构函数的实现,确保正确地管理资源。

总之,在这段代码中调用两次析构函数可能是由于对象的拷贝或移动操作导致的,需要仔细检查代码逻辑和对象的生命周期管理。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

【C++】构造函数函数概念简介 ( 构造函数函数引入 | 构造函数定义与调用 | 函数定义与调用 | 代码示例 )

" 构造函数 " 是 C++ 类的一种特殊的 " 成员函数 " , 该函数不需要用户手动调用 , 而是 C++ 类 实例对象 创建时 , 自动执行的 ; " 函数 " 是 构造函数 的 对应相反的函数...s1, s2; 代码声明了 2 个 Student 变量 , 构造函数调用了 2 次 ; 代码示例 : #include "iostream" using namespace std; class...; 函数返回值 : 函数 没有返回值 ; 2、函数调用 函数调用 : 自动调用 : C++ 编译器会 销毁 C++ 类实例对象时 , 自动调用类的 函数 ; 3、代码示例 - 函数定义与调用...s1, s2; , main 函数执行结束 , 也就是程序终止时 , 会自动调用 ~Student() 函数 , 因此程序退出前 , 会自动为 2 个 Student 对象调用函数 ; 代码示例...函数 函数 栈内存定义了 Student s1, s2; 对象变量 , 栈内存的特点是 后进先出 , 创建时 , 第一个构造函数调用的是 s1 的构造函数 , 第二个构造函数调用的是 s2

17420

Java的“函数”——finalize() 对象消亡时调用

这些特性之一就是函数。取代使用函数,Java 支持finalize() 方法。   本文中,我们将描述 finalize() 与 C++ 函数的区别。...因为这一双重支持,C++ 也提供了自动构造和,这导致了对构造函数函数调用,(对于堆对象)就是内存的分配和释放。    Java ,所有对象都驻留在堆内存,因此局部对象就不存在。...如果finalize() 不是函数,JVM 不一定会调用它,你可能会疑惑它是否在任何情况下都有好处。事实上, Java 1.0 它并没有太多的优点。   ...我们讨论了finalize() 与 C++ 的函数的不同点后,对这个结论不会惊讶,因为为某个类定制的清除代码另一个类不一定会需要。   ...值得C++程序员注意的是,finalize()方法并不能等同与函数。Java是没有函数的。C++的函数是在对象消亡时运行的。

2.9K10

C++不要在构造函数函数调用函数

但是为什么构造函数调用函数,实际上没有发生动态联编呢? 1. 不要在构造函数调用函数的原因 第一个原因,概念上,构造函数的工作是为对象进行初始化。...2.不要在函数调用函数的原因 同样的,函数调用函数函数的入口地址也是在编译时静态决定的。也就是说,实现的是实调用而非虚调用。 考察如下例子。...B的对象b退出作用域时,会先调用类B的函数,然后调用类A的函数函数~A()调用了虚函数show()。...从概念上说,函数是用来销毁一个对象的,销毁一个对象时,先调用该对象所属类的函数,然后再调用其基类的函数,所以,调用基类的函数时,派生类对象的“善后”工作已经完成了,这个时候再调用在派生类定义的函数版本已经没有意义了...因此,一般情况下,应该避免构造函数函数调用函数,如果一定要这样做,程序猿必须清楚,这是对虚函数调用其实是实调用

2.8K30

构造函数以及函数PHP需要注意的地方

构造函数以及函数PHP需要注意的地方 基本上所有的编程语言类中都会有构造函数函数的概念。...C:函数调用,$c // A:函数调用,$b // B:函数调用,$b // A:函数调用,$a 上面的代码是不是有一些内容和我们的预期不太一样?...,则默认调用父类的 函数如果没显式地将变量置为NULL或者使用unset()的话,会在脚本执行完成后进行调用调用顺序测试代码是类似于栈的形式先进后出(C->B->A,C先被),但在服务器环境则不一定...,也就是说顺序不一定固定 函数的引用问题 当对象包含自身相互的引用时,想要通过设置为NULL或者unset()来调用函数可能会出现问题。...关于单例模式为什么要让外部无法实例化的问题,我们可以看看之前的设计模式系统文章的单例模式。

1.6K20

C++核心准则C.82:不要在构造函数函数调用函数

C.82: Don't call virtual functions in constructors and destructors C.82:不要在构造函数函数调用函数 Reason...到目前为止,被调用函数应该只属于构造对象本身,而不是可能存在于派生类的某个覆盖函数。那样做非常难理解。...最坏的情况,构造函数或者函数中直接或间接调用一个没有实现的纯虚函数会导致没有定义的行为。...从构造函数函数调用函数并不是本身有什么错误。这种调用的语义是安全的。然而,经验表明这样的调用很少是必须的,很容易扰乱维护者,如果被新手使用会成为错误源。...提示来自构造函数函数的虚函数调用

74750

C++11 函数执行lambda表达式(std::function)捕获this指针的陷阱

一个简单的例子 下面是一段很简单的lambda测试代码。总体的功能就是让对象时执行指定的std::function函数对象。...test_lambda_base 类的功能很简单,就是函数执行构造函数传入的一个std::function对象。...: 函数体->清除成员变量->基类部分(从右到左)->虚基类部分 所以上面代码test_lambda_base的函数执行子类test_lambda的成员变量fun时,fun作为一个...为了证实这个判断,打开头文件#include 找到function的函数,如下图函数上设置一个调试断点,再运行程序到断点处。 看下图中的”调用堆栈”窗口。...解决问题 解决这个问题的办法很多种, 总的原则就是:如果要在函数调用lambda表达,就要避免lambda使用类成员变量, 对于这个例子,最简单的办法就是修改test_lambda构造函数

1.5K10

【C++】运算符重载案例 - 字符串类 ① ( Visual Studio 创建 String 类 | 构造函数函数 | 完整代码示例 )

, delete 会自动调用函数 ; m_p = new char[m_len + 1]; 最后 , 拷贝空字符串到 m_p 指向的内存 ; // 拷贝空字符串到 m_p 指向的内存 strcpy...strcpy(m_p, p); } cout << "调用有参构造函数" << endl; }; 4、拷贝构造函数 拷贝构造函数 , 使用 String 对象初始化 对象值 ; 首先 ,...strcpy(this->m_p, s.m_p); cout << "调用拷贝构造函数" << endl; } 6、函数 函数 , 使用 delete 释放之前使用 new 分配的内存...; 代码示例 : // 函数 String::~String() { if (this->m_p !...strcpy(this->m_p, s.m_p); cout << "调用拷贝构造函数" << endl; } // 函数 String::~String() { if (this->m_p

20320

c++类和继承面试点25连问

,再调用派生类的构造函数; 派生类对象销毁时,先调用派生类的函数,再调用基类的函数。...= nullptr ) { delete a; } return 0; } 这段代码执行后输出如下: A() B() ~A() 构造的时候是正常的,但是的时候只调用了基类的函数...,能确保派生类的函数会被调用。...因为销毁的时候直接销毁的基类指针,此时编译器只知道调用基类,并不会主动去调用派生类的函数,所以基类函数需为虚函数,这样运行时程序才会去调用派生类的函数,其实这就相当于函数的多态,...基于多态的作用,这个指向派生类的基类指针会先调用派生类的函数,然后再调用基类的函数

90610

Cpp虚函数相关知识点

人要工作,人派生出多个子类后,一个作家工作就是写文章,一个程序员工作却是写代码。工作的执行者不同,工作的内容也不同。 成员函数前面加一个virtual,这个函数就变成了虚函数。...可以看这一篇文章探索C++虚函数g++的实现,讲的很详细。 函数为什么是虚函数 明白了虚函数的特点,这个问题就不难了。...当基类指针指向子类对象的时候,在对象使用完毕需要释放时,肯定需要调用子类对象的函数呀,所以这种情况下函数也得是虚函数。...也可以看这段话: 基类指针可以指向派生类的对象(多态性),如果删除该指针delete []p; 就会调用该指针指向的派生类函数,而派生类的函数又自动调用 基类的函数,这样整个派生类的对象完全被释放...如果函数不被声明成虚函数,则编译器实施静态绑定, 删除基类指针时,只会调用基类的函数而不调用派生类函数, 这样就会造成派生类对象不完全。所以,将函数 声明为虚函数是十分必要的。

36220

类和对象(中篇)

而对象销毁时会自动调用函数,完成对象中资源的清理工作。 特性 函数是特殊的成员函数,其特征如下: 函数名是类名前加上字符 ~。 无参数无返回值类型。...() // main方法根本没有直接创建Time类的对象,为什么最后会调用Time类的函数?...但是: //main函数不能直接调用Time类的函数,实际要释放的是Date类对象,所以编译器会调用Date //类的函数,而Date没有显式提供,则编译器会给Date类生成一个默认的函数...,目的是在其内部 //调用Time类的函数,即当Date对象销毁时,要保证其内部每个自定义对象都可以正确销毁 //main函数并没有直接调用Time类函数,而是显式调用编译器为Date类生成的默认函数...// 注意:创建哪个类的对象则调用该类的函数,销毁那个类的对象则调用该类的函数 如果类没有申请资源时,函数可以不写(自动回收),直接使用编译器生成的默认函数,比如Date类;有资源申请时

6810

构造函数函数可以是虚函数吗,在里面能调用函数

构造函数作为虚函数让人觉得是你的构造函数可能是动态的,那我觉得这可能是另一个设计模式,对象固定,构建方法动态来达到多态的目的,后面这段是我自己的看法 函数作为虚函数?...那么函数作为虚函数什么场景下会用到呢,看看下面这段代码 #include using namespace std; class Father { public: Father...这时候如果是基类指针指向子类对象,那么删除指针,只会调用基类的函数,因为这时候对象类型是基类对象,函数没有动态绑定,只会调用当前对象类型的。...那构造函数里能调用函数吗 这个问题之前腾讯后端一面出现过,我当时有点蒙 首先编译器是允许你这么做的,但是构造函数调用函数,可能达不到你想要的效果,我们看看下面的代码 class Father...//Father f 代码运行后,构造函数调用了父类的虚函数,我们本来想要调用子类的虚函数

1.2K50

多态

所以函数的重写只需要在基类上加上virtual就可以构成重写。 为什么函数进行重写呢?...当我们写成虚函数virtual ~teacher(),构成多态之后,就可以全部正常的对子类释放(调用子类的函数时,先子类,再父类): C++11的 override和final final...要想观察这个调用print是什么方式的,需要看一下汇编代码。 单继承虚函数表 上面那个代码就是单继承,但是上面那个代码,派生类没有写自己的虚函数,只是不继承的虚函数重写了。...静态的成员不能是虚函数,静态成员没有*this指针,静态函数只能用类域的方式调用,而虚函数调用需要在虚函数调用。 构造函数和拷贝构造函数不能是虚函数。...赋值运算符的重载是可以是虚函数函数可以是虚函数,虽然函数函数名不一样,但是在编译器看来,都被处理为destructor,上文有解释为什么要把函数写成虚函数

23220

跟面试官聊.NET垃圾收集,直刺面试官G点

既然有了垃圾收集器,为什么还要Dispose方法和函数? 因为CLR的缘故,GC只能释放托管资源,不能释放非托管资源(数据库链接、文件流等) 那么该如何释放非托管资源呢?...那么就要用到函数了。 函数是个很奇怪的函数调用者无法调用对象的函数函数是由GC调用的。...你无法预测函数何时会被调用,所以尽量不要在这里操作可能被回收的托管资源,函数只用来释放非托管资源 GC释放包含函数的对象,比较麻烦(需要干两次才能干掉她), CLR会先让函数执行,再收集它占用的内存...这个时候就用到了弱引用,来看看下面这段代码: var bss = new BsCtl(BrowserContainer); var vbss = new...//如果没有进行垃圾收集OK不会为NULL if (ok == null) { //如果已经进行了垃圾收集,就会执行这段代码

73360

生成一个C++对象的成本

举个例子吧,就像什么函数总喜欢写成virtual?这个例子应该容易说明virtual的玩法。...就是说,如果不用virtual函数,是没有执行期绑定一说的,比如pObj1这个指针,其实它是Child对象,但是释放时,~Child()方法并没有被调用,仅调用了~Father方法。为什么呢?...因为没有用virtual,就是编译期绑定,当你在编译时gcc/g++只知道pObj1是个Father对象,所以delete时就去调用Father的了。...而如果定义成virtual ~Father时,结果就是一定会Child,这就是为什么函数都要用virtual,因为没人知道会不会有子类继承,否则一旦继承,发生这样的事,函数里万一释放了些资源...即使一个Child对象在编译时被赋为Father类型,但是实际调用时,virtual方法会被单独的拎出来,vtbl中指向实际的实现,所以,该对象delete时会调用Child的函数,而如果你像上面例子那样

45530

【C++】内存管理

代码段(常量区)–可执行的代码/只读常量 而 char2,pChar3 ,ptr1 在内存区域中的划分如下: 首先 “abcd\0” 这段字符串存在常量区,char char2[] = "abcd...2. new和delete操作自定义类型 new/delete 和 malloc/free 最大区别是 new/delete 对于自定义类型除了开空间还会调用构造函数函数,例如以下代码: class.../ 调用函数 return 0; } 注意:申请自定义类型的空间时,new会调用构造函数,delete会调用函数,而 malloc 与 free 不会。...N次构造函数 delete[]的原理 释放的对象空间上执行N次函数,完成N个对象中资源的清理 调用 operator delete[] 释放空间,实际 operator delete[] 调用...申请自定义类型对象时,malloc/free 只会开辟空间,不会调用构造函数函数,而new申请空间后会调用构造函数完成对象的初始化,delete释放空间前会调用函数完成空间中资源的清理。

9810

virtual

函数重载,参数列表不同的目的就是为了,函数调用时编译器能够通过参数来判断程序是调用哪个函数。...这也很自然的解释了为什么函数不能通过返回值不同来重载,因为程序调用函数时很有可能不关心返回值,编译器就无法从代码中看书程序调用的是哪个函数。...指针指向函数就叫函数指针。函数的本质是一段二进制代码,我们可以通过指针指向这段代码的开头。计算就会从这个开头开始执行,直到函数结束为止。...父类指针=new 子类名(……); 父类指针->函数名(……); 调用子类的虚函数函数的实现原理 虚函数的实现原理: 当我们父类通过virtual修饰函数之后,通过父类指针指向子类对象...,这个时候使用父类的指针指向子类的对象,delete接父类指针,就会通过指向的子类的对象找到子类的虚函数表指针,从而找到虚函数表,函数表中找到子类的虚函数,从而使得子类的函数得以执行,子类的函数执行之后系统会自动执行父类的虚函数

63650

【C++干货基地】六大默认成员函数: This指针 | 构造函数 | 函数

没错这就是函数该干的工作了,函数主要负责清理空间和我们以前数据结构的 destroy 销毁空间的作用是一样的!...4.2 函数的特性 函数是特殊的成员函数,其特征如下: 函数名是类名前加上字符 ~。 无参数无返回值类型。 一个类只能有一个函数。若未显式定义,系统会自动生成默认的函数。...注意:函数不能重载 对象生命周期结束时,C++编译系统系统自动调用函数。...,但是程序结束的时候自动调用 关于编译器自动生成的函数,是否会完成一些事情呢?...因为函数一般是用来释放我们申请的空间,而内置类型程序结束会自动释放空间所以没有申请资源可以不写函数

5200
领券