析构函数

关于C++虚函数,纯虚函数以及模板等重要概念的深入讨论(二)

不打扰是莪最后的温柔 提交于 2019-12-24 14:10:18
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 2.析构与虚析构函数 为了说明 基类的析构函数必须为虚析构函数 ,我们来实践一下:在A的析构函数中加入输出cout << "This is A class." << endl;同理在B的析构函数中也加入输出cout << "This is B class." << endl; 最后在main函数objectC->print();下方加入语句:delete objectC; objectC = NULL;从而销毁对象,调用析构函数。如果基类A的析构函数非虚析构的话,运行结果如下: 如果将基类A的析构函数改写为虚析构函数:virtual ~A();那么运行的结果如下: 可以清晰的看到,在基类A中如果是非虚析构函数时,销毁objectC 对象的时候则没有调用B析构函数,而若为虚析构函数的话,就会调用B的析构函数。因此为了防止释放指向子类的基类指针时,子类发生内存泄露现象,我们必须将基类的析构函数设置为虚析构! 3.虚函数与纯虚函数 虚函数即是在声明函数的时候在前面加入virtual 关键字如:virtual void print(); 而纯虚函数则是这样定义的:virtual void print() = 0; 即纯虚函数没有实体,实体是需要它的继承重写来实现的。我们来看一段实例代码: // Test1.cpp :

转帖关于new/delete的运算符和malloc()/free()的标准库函数

随声附和 提交于 2019-12-23 09:48:08
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> new--------delete malloc--------free 问题: 我又一个对象类,里面有一个指针链表,动态分配空间,在析构的时候释放。开始对对象进行new操作,但是执行delete对象操作的时候出错,提示在析构的时候内存有问题。可是这时候成员一个比特的内存都没有分配啊。所以析构的时候应该什么内存操作都不执行。 更奇怪的是采用free()函数就可以释放这种对象,但是内存却不见减少,整个程序内存占用节节升高?这是为什么? 回复1: 你在析构函数当中没有正确的释放你申请的内存,比如,这个对象当中有一个指针,是采用动态申请内存的,在构造函数当中应该把它的值设置为NULL,然后在某个方法当中会申请内存,是采用new方法进行申请的,在析构函当中,应该先判断该指针是否为空,如果不为空,则使用delete释放内存,然后再把该指针设置为NULL。这样就可以了,如果你在外面是采用new申请这个对象,则在使用完成后使用delete释放就可以了。 回复2: 补充一点:new和malloc虽然都是申请内存,但申请的位置不同,new的内存从free store 分配,而malloc的内存从heap分配(详情请看ISO14882的内存管理部分), free store和heap很相似,都是动态内存,但是位置不同

effective C++读书笔记(二)

社会主义新天地 提交于 2019-12-23 03:29:15
5. 编译器会为class自动创建default构造函数,copy构造函数,重载运算符‘=’为copy构造函数,以及析构函数。 自动创建的copy构造函数和‘=’所做的事:将非static成员变量一一拷贝给新对象。 6. 如果不希望对象能够被默认的构造函数copy,例如有些class的对象都比较独特,可以自己将copy构造函数和‘=’声明为private,这样一旦复制操作被误调用,编译器就会报错。 如果父类进行了上述操作,子类则不再需要,即编译器也会阻止子类复制构造函数被调用。 7. 为多态父类声明virtual析构函数 这么做的原因: 当用父类指针指向子类对象时, 例如 base *p = (base *)new derived(); ,由于这个对象存在堆内存需要用delete p来释放内存,但如果父类此时的析构函数不为virtual,则delete操作只会调用父类的析构函数而使得子类的数据不能得到完全回收。 8. 别让异常传出析构函数 9. 不在构造函数和析构函数中调用虚函数 构造函数中的虚函数并不会调用子类的函数,依然是父类。 同样在子类对象调用析构函数时,父类的析构函数会视该对象为父类对象,即析构函数这里并不会发生多态。 10. 让operator返回本对象*this 这样可以让(student a = b)这样的表达式的值仍然为对象b,使得c = a =

c++-虚析构函数

↘锁芯ラ 提交于 2019-12-22 09:22:21
虚析构函数 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <fstream> using namespace std; class A { public: A() { cout << "A()..." << endl; this->p = new char[64]; memset(this->p, 0, 64); strcpy(this->p, "A String.."); } virtual void print() { cout << "A: " << this->p << endl; } virtual ~A() { cout << "~A()..." << endl; if (this->p != NULL) { delete[]this->p; this->p = NULL; } } private: char *p; }; class B :public A { public: B() //此刻会触发A() { cout << "B()..." << endl; this->p = new char[64]; memset(this->p, 0, 64); strcpy(this

AJPFX浅谈Java性能优化之finalize 函数

北城余情 提交于 2019-12-21 00:43:17
★finalize 函数的调用机制   俺经常啰嗦:“了解本质机制的重要性”。所以今天也得先谈谈 finalize 函数的调用机制。在聊之前,先声明一下:Java虚拟机规范,并没有硬性规定垃圾回收该不该搞,以及该如何搞。所以俺这里提到的 finalize 函数的调用机制,或许适用于大多数 JVM,但【不保证】适用于所有的 JVM。 ◇何时被调用?   finalize 啥时候才会被调用捏?一般来说,要等到JVM开始进行垃圾回收的时候,它才【 有可能 】被调用。而 JVM 进行垃圾回收的时间点是【非常】不确定的,依赖于各种运行时的环境因素。正是由于 finalize 函数调用时间点的不确定,导致了后面提到的某些缺点。 ◇谁来调用?   说完何时调用,咱接着来聊一下被谁调用?   常见的 JVM 会通过 GC 的垃圾回收线程来进行 finalize 函数的调用。由于垃圾回收线程比较重要(人家好歹也是 JVM 的一个组成部分嘛),为了防止 finalize 函数抛出的异常影响到垃圾回收线程的运作,垃圾回收线程会在调用每一个 finalize 函数时进行 try/catch,如果捕获到异常,就直接丢弃,然后接着处理下一个失效对象的 finalize 函数。 ★对 finalize 函数的误解和误用 ◇把 finalize 理解为“析构函数”   学过 C++ 的同学应该都知道“析构函数”

面经总结-仅供参考

别等时光非礼了梦想. 提交于 2019-12-20 21:04:52
面经总结-仅供参考 1 服务器如何判断客户端连接不上了 2 心跳包多长时间发一次,如何判断客户端下线了 3 四次挥手 通过什么接口来判断????? 4 epoll只能练500-1000个连接,有没有判断是什么原因引起的 5 noSQL-redis 6 消息队列-应用场景 7 [微服务容器](https://www.cnblogs.com/jsjwk/p/11169296.html) 8 虚函数析构函数和普通虚函数区别,及原因,析构顺序 10 [Redis为什么是单线程的](https://blog.csdn.net/wanderlustlee/article/details/81148840) 11 不同机器进程间如何通信: 12 服务器如何转发消息的 14 西安发消息到上海,接收方消息延迟了,原因 15客户端发了很多消息,服务器怎么及时处理? 16客户端收到大量数据会导致客户端卡顿,怎么优化? 17. 十几个日志文件,用什么shell命令可以筛选出自己想要的日志内容 18. 客户端连接不上服务器的问题一般怎么定位?(未解决) 19. [多进程文件怎么共享,为什么要用mmap。](https://blog.csdn.net/tencupofkaiwater/article/details/88897529) 20. [vi打开文件后,怎么替换无数个想要替换的内容](https:/

C#中值类型和引用类型

廉价感情. 提交于 2019-12-19 11:39:15
概念: 1.值类型:数据存储在内存的堆栈中,从堆栈中可以快速地访问这些数据,因此,值类型表示实际的数据。 2.引用类型:表示指向存储在内存堆中的数据的 指针或引用 (包括类、接口、数组和字符串)。 C#中定义的值类型包括原类型( Sbyte、Byte、Short、Ushort、Int、Uint、Long、Ulong、Char、Float、Double、Bool、Decimal )、枚举( enum )、结构( struct) 引用类型包括:类、数组、接口、委托、字符串等。 区别: 基本区别在于它们在内存中的 存储方式 。 值类型 只将值存放在内存中,这些值类型都存储在堆栈中。原始数据类型(如bool和int)都属于此类型。而 引用类型 的内存单元中只存放内存堆中对象的地址,而对象本身放在内存堆中。如果引用的值类型的值是null,则表示未引用任何对象。 堆和堆栈区别 : 堆和堆栈是两个不同的概念,在内存中的存储位置也不相同, 堆一般用于存储可变长度的数据,如字符串类型; 堆栈则用于存储固定长度的数据,如整型类型的数据int(每个int变量占用四个字节)。由数据存储的位置可以得知,当把一个值变量赋给另一个值变量时,会在堆栈中保存两个完全相同的值;而把一个引用变量赋给另一个引用变量,则会在堆栈中保存对同一个堆位置的两个引用,即在堆栈中保存的是同一个堆的地址。在进行数据操作时,对于值类型

析构函数何时被调用

旧巷老猫 提交于 2019-12-19 07:47:10
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> 析构函数何时被调用 析构函数在下边3种情况时被调用: 对象生命周期结束,被销毁时; 主动调用delete ; 对象i是对象o的成员,o的析构函数被调用时,对象i的析构函数也被调用。 第一种情况 #include <iostream> using namespace std; class A { public: A() { cout << "constructing A" << endl; } ~A() { cout << "destructing A" << endl; } private: int a; }; void main() { A a; } 运行结果: constructing A destructing A 1 2 第二种情况 如果是new的对象,即使离开了作用域也会一直存在,必须主动delete,否则只有在结束程序时才会执行析构。这里在说下内存泄漏,举个例子 #include <iostream> using namespace std; class A { public: A() { cout << "constructing A" << endl; } ~A() { cout << "destructing A" << endl; } private: int a; }; void fun(

3.继承与派生

只愿长相守 提交于 2019-12-18 15:18:19
1.类的继承与派生   - 类的继承:从已有类产生新类的过程。原有类称为基类或父类,产生的新类称为派生类或子类。   - 派生类语法:       class 派生类名:继承方式 基类名1,继承方式  基类名2,...     {     }   - 单继承和多继承:基类个数决定   - 直接基类,间接基类   - 继承方式规定了如何访问从基类继承的成员   - 派生类成员是指除了从基类继承的所有成员之外,新增加的数据和函数成员   - 派生类生成过程:吸收基类成员->改造基类成员->添加新的成员,构造函数和析构函数都不被继承 2.访问控制   - public:继承后,基类数据为public   - protected:继承后,基类数据为protected   - private:继承后,基类数据为private 3.类型兼容性规则:指在需要基类的任何地方,都可以使用公有派生类的对象来代替(公有继承)   - 代替包含以下情况     * 派生类的对象可以隐含转换为基类对象     * 派生类对象可以初始化基类的引用     * 派生类的指针可以隐含转换为基类指针   - 在代替之后,派生类对象就可以作为基类的对象使用,但只能使用从基类继承的成员 4.派生类的构造和析构函数   - 构造函数:     派生类构造函数执行的一般次序     * 调用基类构造函数

Java finalize方法使用

一个人想着一个人 提交于 2019-12-17 16:26:30
《 JAVA 编程思想》: Java 提供 finalize () 方法,垃圾回收器准备释放内存的时候,会先调用 finalize() 。 (1).对象不一定会被回收。 (2).垃圾回收不是析构函数。 (3).垃圾回收只与内存有关。 (4).垃圾回收和finalize()都是靠不住的,只要JVM还没有快到耗尽内存的地步,它是不会浪费时间进行垃圾回收的。 有时当撤消一个对象时,需要完成一些操作。例如,如果一个对象正在处理的是非Java 资源,如文件句柄或window 字符字体,这时你要确认在一个对象被撤消以前要保证这些资源被释放。为处理这样的状况,Java 提供了被称为收尾(finalization )的机制。使用该机制你可以定义一些特殊的操作,这些操作在一个对象将要被垃圾回收程序释放时执行。 要给一个类增加收尾(finalizer ),你只要定义finalize ( ) 方法即可。Java 回收该类的一个对象时,就会调用这个方法。在finalize ( )方法中,你要指定在一个对象被撤消前必须执行的操作。垃圾回收周期性地运行,检查对象不再被运行状态引用或间接地通过 其他 对象引用。就在对象被释放之前,Java 运行系统调用该对象的finalize( ) 方法。 finalize()方法的通用格式如下: protected void finalize( ) { //