析构函数

重读STL源码剖析:析构

寵の児 提交于 2019-11-29 10:30:19
纯虚析构函数 理论上来说,将一个函数声明为纯虚函数后,这个类即变为抽象类。纯虚函数只提供接口,而不提供实现,但纯虚析构函数一定要提供定义。这是由C++特性决定的,编译器对派生类的析构函数会进行扩展,以静态调用的方式调用其每一个虚基类和上基类的析构函数,尽管是一个抽象类,但仍然要为这个纯虚析构提供实现,即使是awov::~awov() {} 这样没有任何操作的实现,因为如果不提供,将导致链接失败 虚函数与内联 内联函数是一种静态行为,由编译器在调用地点展开,这是在编译期进行的;而虚函数是一种动态行为,是在运行期通过虚函数表跳转来实现的,因此inline与virtual是矛盾的,之所以声明为virtual的内联函数能成功运行,这是因为编译器做了优化。inline是对编译器的一种建议,而编译器是否采纳则不一定。j 来源: https://www.cnblogs.com/lxy-xf/p/11515570.html

C#实现IDispose接口

风流意气都作罢 提交于 2019-11-29 09:42:24
C#实现IDispose接口 .net的GC机制有两个问题:首先GC并不能释放所有资源,它更不能释放非托管资源。其次,GC也不是实时的,所有GC存在不确定性。 为了解决这个问题donet提供了析构函数 public class TestClass : System.IDisposable { //供程序员显式调用的Dispose方法 public void Dispose() { //调用带参数的Dispose方法,释放托管和非托管资源 Dispose(true); //手动调用了Dispose释放资源,那么析构函数就是不必要的了,这里阻止GC调用析构函数 System.GC.SuppressFinalize(this); } //protected的Dispose方法,保证不会被外部调用。 //传入bool值disposing以确定是否释放托管资源 protected void Dispose(bool disposing) { if (disposing) { ///TODO:在这里加入清理"托管资源"的代码,应该是xxx.Dispose(); } ///TODO:在这里加入清理"非托管资源"的代码 } //供GC调用的析构函数 ~TestClass() { Dispose(false);//释放非托管资源 } } 而即使我们忘记了在合适的时候调用Dispose

【学习总结】boost智能指针

帅比萌擦擦* 提交于 2019-11-29 06:31:47
一、为什么使用智能指针 为管理内存等资源,C++采取RAII机制(资源获取即初始化,Resource Acquisition Is Initialization),在使用资源的类的构造函数中申请资源并使用,最终在析构函数中释放资源。使用new在堆上创建对象时,其析构函数不会自动调用,需要使用delete才能释放资源,若因为异常导致程序未能执行delete,则存在内存泄露的问题。C++98标准中的“自动指针std::auto_ptr(C++11中废弃,改用unique_ptr)部分解决了获取资源自动释放的问题。 二、boost库提供的智能指针 boost.smart_ptr库提供六种智能指针,包括socped_ptr、scoped_array、shared_ptr、shared_array、weak_ptr和intrusive_ptr。他们都是轻量级的对象,速度与原始指针相差无几,都是异常安全的,而且对于所指向的类型T也仅有一个很小且合理的要求:类型T的析构函数不能抛出异常。 头文件:#include<boost/smart_ptr.hpp> scoped_ptr 保证智能指针只能在本作用域中使用,拥有对象的唯一所有权,不可以复制。如果一个类中有scoped_ptr成员变量,则该类也不可拷贝或赋值。 <boost/scoped_ptr.hpp> scoped_array

Java finalize方法

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

多态中的虚析构函数

只愿长相守 提交于 2019-11-29 00:17:38
为什么析构函数要声明成virtual呢? 因为,如果delete一个基类的指针时, 如果它指向的是一个子类的对象,那么析构函数不为虚就会导致无法调用子类析构函数,从而导致资源泄露。 如果一个类要被使用成 多态 的,那么这个 virtual是必须 的。比如: #include <iostream> using namespace std; class Animal { char* ap; public: Animal() { ap = new char; std::cout << "Animal ctor" << std::endl; } virtual void foo() { std::cout << "Animal::foo" << std::endl; } virtual ~Animal() { std::cout << "Animal dtor" << std::endl; delete ap; } }; class Dog : public Animal { char* dp; public: Dog() { dp = new char; std::cout << "Dog ctor" << std::endl; } virtual void foo() { std::cout << "Dog::foo" << std::endl; } virtual ~Dog() {

C++ 之 智能指针 知识点

末鹿安然 提交于 2019-11-28 20:05:05
我们知道除了静态内存和栈内存外,每个程序还有一个内存池,这部分内存被称为自由空间或者堆。程序用堆来存储动态分配的对象即那些在程序运行时分配的对象,当动态对象不再使用时,我们的代码必须显式的销毁它们。 在C++中,动态内存的管理是用一对运算符完成的:new和delete,new:在动态内存中为对象分配一块空间并返回一个指向该对象的指针,delete:指向一个动态独享的指针,销毁对象,并释放与之关联的内存。 动态内存管理经常会出现两种问题:一种是忘记释放内存,会造成内存泄漏;一种是尚有指针引用内存的情况下就释放了它,就会产生引用非法内存的指针。 为了更加容易(更加安全)的使用动态内存,引入了智能指针的概念。智能指针的行为类似常规指针,重要的区别是它负责自动释放所指向的对象。标准库提供的两种智能指针的区别在于管理底层指针的方法不同,shared_ptr允许多个指针指向同一个对象,unique_ptr则“独占”所指向的对象。标准库还定义了一种名为weak_ptr的伴随类,它是一种弱引用,指向shared_ptr所管理的对象,这三种智能指针都定义在memory头文件中。 为什么用: 为了更加容易,更加安全的使用动态内存 ,有了智能指针。 是什么:智能指针是一个 负责自动释放所指向的对象 的指针。 有四种:shared_ptr,unique_ptr,weak_ptr,scoped_ptr

C/C++基础知识点面试题

北城以北 提交于 2019-11-28 19:21:44
目录 一、虚函数的数据结构,如何工作? 二、const与define的区别? 三、指针与引用的区别? 四、指针与数据的区别? 五、不用临时变量实现两个变量的交换 七、一个C++源文件从文本到可执行文件经历的过程 八、C++11新特性 九、C++和C的不同 十、malloc的原理 十一、内存泄漏、野指针 十二、static 十三、union和struct 十四、new与malloc的区别 十五、C++类型转换 十六、面向对象的了解 十七、前置和后置的区别 十八、静态库和动态库 十九、struct内存大小的确定 二十、strlen,strcpy函数的实现 二十一、memcpy,memset内部函数实现 二十二、C/C++内存管理方式,内存分配 二十三、深拷贝和浅拷贝 二十四、debug和release的区别 二十五、main是否需要返回值? 二十六、C++动态链接库与C动态链接库 二十七、结构体 二十八、拷贝构造函数为什么传引用? 二十九、程序崩溃原因 三十、C++字符串输入 三十一、lambda表达式 一、虚函数的数据结构,如何工作? 虚函数:用virtual定义的函数为虚函数。 虚函数来源:基于C++的一个特性:子类能转换成父类,例如: CBasic *parent; CBasic *p1; CChildren *child; parent = new CBsic; child =

光棍节就要到了,要不要给你介绍个 python 对象?

穿精又带淫゛_ 提交于 2019-11-28 19:06:14
文章目录 1. 前言 2. 类和对象的概念 3. 类的成员 4. 新式类和旧式类 5. 静态变量和实例变量 6. 静态函数 7. 面向对象三要素 (1) 继承 (2) 封装 (3) 多态 8. 抽象类 9. 单例模式 10. 后记 1. 前言 光棍节就要到了,一说介绍对象,我猜你一定想到了派森大叔家的克蕾丝(class)小姐姐和黛夫(def)小哥哥。别想入非非了,严肃点儿!我们今天的的话题,不是介绍男女朋友,而是讲解如何面向对象编程,也就是程序员常说的OOP啦。 不知道前辈们为什么会把 Object Oriented Programming 翻译成面向对象编程,搞得单身程序员经常心猿意马地产生幻觉,以为屏幕上的俊男美女就是自己将来要面对的对象了。说到这里,我觉得还是台湾同行的计算机术语翻译得较为恰当。比如,cache,我们叫“缓存”,人家叫“快取”,音意俱佳。台湾同行把OPP翻译成“物件导向编程”——虽然同样不明觉厉,但至少可以让单身程序员暂时忘记没有“对象”的烦恼。 限盐少许,本博主正式开始为大家介绍对象。 2. 类和对象的概念 学习面向对象编程,首先得搞明白,什么是对象?类是什么?实例化是什么意思?下图表达了我对OOP这几个基本概念的理解(实际上是妥协的结果——我和我的同事们讨论了很久,并翻墙参考了维基百科的说法)。 类是对我们要处理的客观事物的抽象

new/delete和malloc/free区别与联系

我的未来我决定 提交于 2019-11-28 12:53:28
1、基本概念 malloc/free (1)、函数原型及说明 void *malloc(long NumBytes): 该函数分配了NumBytes个字节,并返回了指向这块内存的指针。如果分配失败,则返回一个空指针NULL。 void free(void *FirstByte): 该函数是将之前用malloc分配的空间还给程序或者是操作系统,也就是释放了这块内存,让它重新得到自由。 (2)、内存操作 malloc函数的参数是接受需要分配的内存字节数,如果内存能够满足请求量,那么将会返回:指向被分配的内存块起始位置; free函数释放的是指针指向的内存(不是释放的指针本身,不会删除指针本身) ,其中指针必须指向所释放内存空间的首地址。 new/free (1)、操作时发生事件 new的时候会有两个事件发生: 1)、内存被分配(通过operator new 函数); 2)、为被分配的内存调用一个或多个构造函数构建对象。 delete的时候,也有两件事发生: 1)、为将被释放的内存调用一个或多个析构函数; 2)、释放内存(通过operator delete 函数)。 (2)、特殊应用 使用delete是未加括号,delete便假设删除对象是单一对象,否则便假设删除对象是个数组。 因此,如果在调用new时使用了[],则在调用delete时也使用[],如果你在调用new的时候没有[]

PHP 构造函数和析构函数

馋奶兔 提交于 2019-11-28 11:14:30
构造函数 __construct ([ mixed $args [, $... ]] ) : void PHP 5 允行开发者在一个类中定义一个方法作为构造函数。具有构造函数的类会在每次创建新对象时先调用此方法,所以非常适合在使用对象之前做一些初始化工作。 Note: 如果子类中定义了构造函数则不会隐式调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。如果子类没有定义构造函数则会如同一个普通的类方法一样从父类继承(假如没有被定义为 private 的话)。 Example #1 使用新标准的构造函数 <?php class BaseClass { function __construct() { print "In BaseClass constructor\n"; } } class SubClass extends BaseClass { function __construct() { parent::__construct(); print "In SubClass constructor\n"; } } class OtherSubClass extends BaseClass { // inherits BaseClass's constructor } // In BaseClass