BetterTs

鸢飞戾天者,望峰息心;经纶世务者,窥谷忘反
C++

虚函数总结

虚函数 虚函数在C++中的基类由关键字vritual声明,允许在一个或多个派生类中重新定义。虚函数通过指向派生类中的基类指针或引用来实现多态性,多态性就是将接口与实现进行分离,能且仅能通过指针或引用可以访问派生类中的同名覆盖函数。 多态是什么 联编:联编就是将模块或者函数合并在一起生成可执行代码的处理过程,同时对每个模块或者函数调用分配内存地址,并且对外部访问也分配正确的内存地址,它是计算机程序彼此关联的过程。 多态也称为动态联编或迟后联编,因为到底调用哪一个函数,在编译时不能确定,而要推迟到运行时确定。也就是说,要等到程序运行时,确定了指针所指向的对象的类型时,才能够确定。 C++ 多态意味着调用成员函数时,会根据调用函数的对象的类型来执行不同的函数。 实现多态的三个条件: 存在继承关系 重写父类的virtual function 子类以父类的指针或者是引用的身份出现 为什么需要虚函数 多态性是面向对象设计语言的基本特征。仅仅是将数据和函数捆绑在一起,进行类的封装,使用一些简单的继承,还不能算是真正应用了面向对象的设计思想。 实例 Class Base{ public: void print(){ cout<<"This Class is Base Class"<<endl; } } Class A : public Base{ void print(){ cout<<"This Class is A Class"<<endl; } } int main(){ Base ba; A b; ba.print(); b.print(); } 上述示例输出: This Class is Base Class This Class is A Class 此实例并没有实现多态,只是单纯的调用而已。 只有子类以父类的引用或函数的指针形式调用时才能出现多态。 若以指针方式调用而不以virtual修饰父类函数: Class Base{ public: void print(){ cout<<"This Class is Base Class"<<endl; } } Class A : public Base{ void print(){ cout<<"This Class is A Class"<<endl; } } int main(){ Base ba; A b; Base* ptr_base = &ba; Base* ptr_b = &b; ptr_base->print(); ptr_b->print(); } 输出的是: This Class…

C++

智能指针

四种智能指针 介绍 智能指针主要用于管理在堆上分配的内存,它将普通的指针封装为一个栈对象。当栈对象的生存周期结束后,会在析构函数中释放掉申请的内存,从而防止内存泄漏。C++ 11中最常用的智能指针类型为shared_ptr,它采用引用计数的方法,记录当前内存资源被多少个智能指针引用。该引用计数的内存在堆上分配。当新增一个时引用计数加1,当过期时引用计数减一。只有引用计数为0时,智能指针才会自动释放引用的内存资源。对shared_ptr进行初始化时不能将一个普通指针直接赋值给智能指针,因为一个是指针,一个是类。可以通过make_shared函数或者通过构造函数传入普通指针。并可以通过get函数获得普通指针。 C++里面的四个智能指针: auto_ptr, shared_ptr, weak_ptr, unique_ptr 其中后三个是c++11支持,并且第一个已经被11弃用。 使用智能指针的原因:在使用new/delete管理动态内存时有可能会存在以下问题 忘记释放内存,造成内存泄露 忘记已经释放过 释放多次 异常的内存泄漏 使用智能指针可以很大程度上的避免这个问题,因为智能指针就是一个类,当超出了类的作用域是,类会自动调用析构函数,析构函数会自动释放资源。所以智能指针的作用原理就是在函数结束时自动释放内存空间,不需要手动释放内存空间。 auto_ptr autr_ptr模板定义了类似指针的对象,可以将new直接或间接获得的地址赋给这种对象,智能指针过期时,析构函数将调用delete来释放内存。因此,如果将new返回的地址赋给这种对象,将无需记住稍后要释放内存,智能指针过期时,这些内存将自动被释放。 这种特性和其他三种智能指针在行为上相似。 普通指针和智能指针的区别 示例代码 void Demo_1(){ double* pd = new double; #1_1 *pd = 25.5; #1_2 return; #1_3 } void Demo_2(){ autr_ptr<double> ap = new double; #2_1 *ap = 25.5; #2_2 return; #2_3 } 1_1 : 为pd和一个double值分配空间,保存地址 pd(地址400) –> 地址1000 1_2 : 为动态地址1000存上一个值 pd(地址400) –> 地址1000(存25.5) 1_3 : 删除pd,值被保留在动态内存中 pd(地址400) 地址1000(存25.5) 2_1 : 为ap和一个double值分配空间,保存地址 pd(地址400) –> 地址1000 2_2 : 为动态地址1000存上一个值 pd(地址400) –> 地址1000(存25.5) 2_3 : 删除ap,并且释放动态内存 pd(地址400) –> 地址1000(存25.5) auto_ptr采用所有权模式 auto_ptr< string> p1 (new string ("I reigned lonely as a cloud.”)); auto_ptr<string> p2; p2 = p1; //auto_ptr不会报错. 此时不会报错,p2剥夺了p1的所有权,但是当程序运行时访问p1将会报错。所以auto_ptr的缺点是:存在潜在的内存崩溃问题! unique_ptr unique_ptr实现独占式拥有或严格拥有概念,保证同一时间内只有一个智能指针可以指向该对象。它对于避免资源泄露(例如“以new创建对象后因为发生异常而忘记调用delete”)特别有用。 auto_ptr< string> p1…

技术

初等排序

初等排序 冒泡排序、选择排序和插入排序的时间复杂度都是$$ O(n^2)$$,都是排序算法中较为基础的算法,也统称为初等排序算法。一般作为排序算法的入门。 三种排序算法的思想都是将数据分为已排序部分和未排序部分再做相应处理。 实例 输入 第一行输入数组长度整数N,第二行输入N个整数,以空格隔开 输出 输出排序结果 限制 1<=N<=100 插入排序 伪代码 InsertionSort(A,N)//包含n个元素的数组A for i=1 to N-1 v=A[i] j=i-1 while j>=0 and A[j]>v//移动比A[i]大的元素 A[j+1]=A[j] j-- A[j+1]=v//插入操作 算法原理 将开头元素视作已排序部分 取出未排序部分的开头元素赋值给v 在已排序部分,所有比v大的元素都往后移动一个单位 将取出的元素v插入空位 循环2-4直至未排序部分消失 源码 #include <iostream> using namespace std; void InsertionSort(int A[],int N){ int j,v; for(int i=1;i<N;i++){ v=A[i]; j=i-1; while(j>=0&&A[j]>v){ A[j+1]=A[j]; j--; } A[j+1]=v; } } int main(){ int N,i,j; int A[100]; cin>>N; for(i=0;i<N;i++){ cin>>A[i]; } InsertionSort(A,N); for(i=0;i<N;i++){ cout<<A[i]<<" "; } } 输出结果 冒泡排序 伪代码 BubbleSort(A,N) flag=1//存在顺序相反的相邻元素 i=0//未排序部分的起始下标 while(flag) flag=0 for j=N-1 downto 1 if A[j]<A[j-1] swap(A[j-1],A[j])//交换 flag=1 i++ 算法思想 待排序数组A分为已排序部分和未排序部分 从数组末尾开始依次比价相邻元素,如果大小相反则交换位置 源码 #include <iostream> using namespace std; void Swap(int *a,int *b){ *a=*a+*b; *b=*a-*b; *a=*a-*b; } void BubbleSort(int A[],int N){…

技术

计算机的启动过程

计算机的启动过程是一个十分复杂的过程,了解启动过程前,我们需要先理解以下基本概念 基本概念 BIOS     BIOS(原意Basic Input/Ouput System,基本输入输出系统),全称是ROM-BIOS。BIOS(Basic Input/Output System,基本输入输出系统)全称是ROM-BIOS,是只读存储器基本输入/输出系统的简写,它实际是一组被固化到电脑中,为电脑提供最低级最直接的硬件控制的程序,它是连通软件程序和硬件设备之间的枢纽,通俗地说,BIOS是硬件与软件程序之间的一个"转换器"或者说是接口(虽然它本身也只是一个程序),负责解决硬件的即时要求,并按软件对硬件的操作要求具体执行。 自诊断程序:通过读取CMOS RAM中的内容是被硬件配置,进行自检和初始化。 CMOS设置程序:引导过程中,用特殊热键启动,进行设置后存入CMOS RAM中。 Boot:系统自举装载程序,自检成功后将磁盘相对0道0扇区上的引导程序装入内存。   计算机的启动过程一般分为四个阶段 第一阶段:BIOS 开机程序BIOS被刷入ROM中,通电启动后主要做以下几件事 1.1硬件自检 BIOS启动后,首先检查硬件是否满足基本的条件,如果硬件出现问题,主板就会发出蜂鸣声,启动终止,电脑死机。此过程叫Power-On Self-Test,缩写POST。 1.2确定启动顺序-加载引导扇区 在硬件自检完成后,BIOS的主要工作就是加载引导扇区。BIOS会把控制权交给下一阶段的启动程序。此时BIOS需要外部有一个外部存储设备的顺序表(Boot Sequence),在此顺序表中排在前面的设备具有优先启动权。 第二阶段:主引导记录     主引导记录,MBR,是存储设备的第一个扇区。 BIOS按照启动顺序,把控制权交给排在第一位的存储设备。BIOS将所检查外部存储设备的第一个扇区(512B)载入内存,放在0x00007C00处,如果一个扇区的最后两个字节是"55 AA",那么这就是一个引导扇区,这个外部存储设备也就是一块可引导盘。通常这个大小为512B的程序就称为引导程序(boot)。如果最后两个字节不是"55 AA",那么BIOS就检查下一个外部存储设备。如果没有其他启动介质,则显示 "No ROM BASIC" ,然后死机。 2.1MBR的结构 调用操作系统的机器码:占据1-446字节 分区表:占据447-510字节 主引导记录签名:占据511-512字节(即0x55和0xAA) 分区表的作用是将硬盘分成若干个区。 2.2分区表 分区表的长度只有64个字节,里面又分为四项,每一项16个字节。因此每一个硬盘最多只有四个一级分区,这些一级分区就是"主分区"。 每个主分区的16字节,由6个部分组成: 第1个字节:该字节用于标识控制权能否转交给该分区,若为0x80,就表示该分区是激活分区,控制权需要装交给该分区。四个主分区只能由一个是激活的。 第2-4个字节:标识了主分区里第一个扇区的物理位置(磁头、柱面、扇区号等等) 第5个字节:标识了主分区的类型。 第6-8个字节:标识了主分区最后一个扇区的物理位置。 第9-12个字节:该主分区第一个扇区的逻辑位置。 第13-16个字节:主分区的扇区总数 最后的四个字节决定了主分区的长度,主分区扇区总数不超过2^32 第三阶段:硬盘启动 到此阶段,计算机的控制权就要转交给硬盘的某个分区了。 3.1卷引导记录 四个主分区里面,只有一个是激活的。计算机会读取激活分区的第一个扇区,叫做"卷引导记录"(Volume Boot Record,缩写为VBR,也可称为分区引导记录,Partition Boot Record,缩写为PBR)。 "卷引导记录"的主要作用是,寻找激活分区根目录下的NTLDR(XP)、bootmgr(Win7 above)、grldr(Grub)、btldr.mbr(BootLink)等可用于引导的程序。   3.2启动管理器 启动管理器是系统预先安装的程序,可由用户选择启动哪一个操作系统。卷引导记录搜索到激活分区中的启动管理器,将控制权交给启动管理器运行。 启动管理器寻找激活分区中的启动配置文件,根据启动配置数据,在显示器上显示多操作系统选择画面。选择相应的操作系统,控制权交给操作系统。 Linux环境中,目前最流行的启动管理器是Grub。在windows下为启动管理器bootmgr(xp中的ntldr文件)。 第四阶段:操作系统 控制权转交给操作系统后,操作系统的内核首先被载入内存。 以Linux系统为例,先载入/boot目录下面的kernel。内核加载成功后,第一个运行的程序是/sbin/init。它根据配置文件(Debian系统是/etc/initab)产生init进程。这是Linux启动后的第一个进程,pid进程编号为1,其他进程都是它的后代。 然后,init线程加载系统的各个模块,比如窗口程序和网络程序,直至执行/bin/login程序,跳出登录界面,等待用户输入用户名和密码。 至此,全部启动过程完成。         参考文献     《计算机是如何启动的?》阮一峰

随笔

谈“不信任关系”

一直以来,因为某些原因,我总想寻找一个词去定义人与人之间的相处模式,经过粗浅的思考,我不那么慎重的决定用"不信任关系"这样一个词语来描述它。   "信任关系"与"不信任关系" "不信任关系"脱胎于"信任关系"一词,信任关系是KPI(公钥基础设施)模型里的概念,指的是当两个认证机构中的一方给对方的公钥颁发证书或者双方给对方的公钥颁发证书时,两者之间就建立了信任关系。信任关系的概念科学严谨且形象的定义了信任是如何建立的——人和人相处到了某一个状态,无形间便单方面或互相的发送了"凭证"从而形成了信任关系。遗憾的是,大多数人之间是无法亲密到形成"信任关系"的——还没等到给彼此发证,人们便早早的停止了相处。可以说,"不信任关系"是对现在大多数人际关系的概括。   "信任危机"与"不信任关系" 有思考"人际关系问题的根源是什么"这样的想法来缘于当下我在大学校园里体验到的和观察到的信任危机。一方面,人际关系里的信任度往往可以从人们对人性的态度上体现出来,社会急剧转型状态下,大学生们(不仅仅是大学生)在人际交往中往往成为了理性计算自身利益得失而把对方当做"工具人"的"经济人"。在他们身上普遍理想主义丧失,个人主义和拜金主义盛行。舞弊、偷盗、拖欠贷款,造假等等行为也从一个侧面反应了当代大学生们的价值取向变化。另一方面,难以交到真正的知心朋友,无处倾诉成为大学生们的普遍问题,同时,大学生群体也是近年来抑郁和自杀的高发群体。这一点,在文献里得到了佐证。 因此,我用"不信任关系"来描述大多数孤立个体之间的相处模式。并且我相信,这样的相处模式在将来很长一段时间任然会是大多数人的相处模式。   信任与信任的重要性 信任是探讨"不信任关系"的前提和基础。尽管在各个学科领域,信任并没有一个特别明确统一的概念,但是我们仍然可以感性的去认识它。信任的过程是彼此交付心灵的一个过程。信任本身意味着不可控的危险,信任的产生像是生长一棵深植于心的树,信任别人的同时,也赋予了别人伤害我们的权利。 信任是一种依赖关系,是交换关系的基础,而人际关系的本质就是一种"社会交换"。同样的,信任也是欺骗、背叛等等人际关系里各种伤害的基础和前提。没有信任,伤害和背叛也就无从谈起。 阿德勒(《自卑与超越》的作者)说,所有人的问题都是人际关系的问题,而精神动力学则指出,所有人际关系的问题都是不信任的问题。信任的复杂性和重要性决定了它在人际交往中不一样的地位,获取信任是人与人深入相处的基础。 "不信任关系"从何而来 导致人际关系由"信任关系"变为"不信任关系"的原因通常有两种,一是相处达不到建立信任关系的地步;二则是因为背叛、欺骗等等原因导致关系恶化为"不信任关系"。 由于家庭、人生观等各种各样的原因,人们总是不能轻易地达成"信任关系"。进一步的,信任是一种脆弱的状态。通过经验总结我们会发现,人和人之间的信任总会轻易被破坏。人际关系的破裂是人生中最痛苦的事情之一,每一个人都会极力避免,错误的捆绑方式会加速人际关系的破裂,就算暂时维系了彼此的关系,这样的关系也只是浮于表面,十二万分之脆弱。 一切关系的源头,我们都得从过去谈起。过去无数点点滴滴的事情无不汇聚到现在组成了此时此刻的我们。往往是我们的过去决定了我们的现在,几乎所有的心理问题归根结底都是关系的问题。埃里克森在他的人格发展八阶段理论里指出,人格发展的第一个危机就是婴儿前期的基本的信任同不信任的心理冲突危机。家庭关系在人的童年时期定下人性格的基调,而往后的人际关系则在不断的往这座性格大厦上添砖加瓦。家庭关系紧张,容易造成孩子的精神问题,不和谐的家庭会对孩子的性格、成长乃至整个人生产生不可磨灭的影响。原生家庭的不幸往往需要用一生的不幸来治愈。和谐美好的家庭关系总是给予孩子积极向上的正能量。究其根本,"不信任关系"便是从家庭开始的。 当然了,一个人的成长并不只是由过去的某一个点决定的,成长一直是一个长期的过程。家庭往后的"不信任关系"往往体现在朋友或恋人之间的背叛、欺骗和各种伤害。 "不信任关系"带来什么 "不信任关系"带来的结果并不同信任一样显而易见。同那句老话说的一样,幸福总是相似的,不幸却各有各的不同。厌世、内向、自卑、社恐,抑郁甚至用道德的鞭子鞭笞那些离开自己的人一定程度上都是"不信任关系"带来的结果。更有甚者,这样的影响直接体现在交不到朋友或者无法交到知心朋友上。"不信任关系"导致了自我性格和心理上各种各样的缺陷,最后呈现出社交无能,无法正常融入社会的状态。安全感缺失是"不信任关系"带来了另一大问题。安全感缺失和"不信任关系"是一个难以破解的死循环,靠自我的力量往往难以做出改变。 尽管"不信任关系"给我们带来各种各样的问题,但是实际上,每个人或多或少都存在性格缺陷和心理问题,完美的人在现实生活里是不存在的,"不信任关系"在现在的人际交往中才是常态。   如何进行自我治愈并克服"不信任关系" 治愈的前提是认识自我。对自身缺陷和优点的认识可以让自己有一个清晰的定位。我们需要认识到的是,人际吸引从来都不是靠的完美,这个世界上并不存在完美的人,如果我们需要或喜欢对方身上的某个特质,我们就愿意忍受其他的缺陷和对方在一起。 其次便是适度的原谅和遗忘。面对或家庭或朋友或恋人的伤害,我们往往无能为力,有的人把自己内化为一个惩罚者,责备他人的同时,自己也受过去的惩罚。原谅并不是说对对方无限制的原谅和满足,更多的是对自我的不完美、不顺遂甚至是过去的一些错误的原谅。痛苦上天赐予我们的一项宝贵财富,这些经历折磨我们的同时也塑造了我们。但是,人的精力是有限的,只有遗忘掉一些痛苦不堪的东西,我们才能更好的往前走,才能成为更好的自己。 最后便是大胆的走出去。关系的问题最终要回到关系里去才能改善,不能因噎废食。积极的走出去,在合适的探索与尝试中逐步改善自我的性格缺陷。一个人或许可以走的很快,但一群人才能走得更远。 否定之否定规律告诉我们,事物发展的前进性与曲折性是相互统一的。治愈的过程同样不是一成不变的,或许会有曲折,但是只要小心尝试,那就总是在不停的改变。我们先明白我是一个什么样的我,然后才会吸引另外的人来圆满自己,或者说是分享自己的圆满。   写在最后的结束语 人际危机和心理问题方面上的探讨永远不会结束,也很难有一个统一的观点,就如同我依然悲观的认为这种"不信任关系"会持续很久。但是比这更需要明白的是,人的成长本就离不开各种各样的问题。尽管你会受到这样那样的恶意揣测、诋毁或者是其他的伤害,但其实这并不妨碍我们健康快乐的成为自己。探讨问题一方面使我们更加清晰的认识自己,另一方面也使自我得到更多的成长! 而面对这些问题,我们所需要做的就是——先成为温暖的自我,再去温暖别人!