美文网首页
C++面向对象程序设计(上)第二周学习笔记——Boolan

C++面向对象程序设计(上)第二周学习笔记——Boolan

作者: GINNYAK | 来源:发表于2017-06-21 22:41 被阅读0次

    在完成了C++面向对象高级编程(上)第二周的学习之后,有一些总结和心得在这里通过学习笔记的方式分享出来,供也在学习C++的小伙伴用作学习交流,如有理解不到位的地方,欢迎批评指正。

    本周学习了Class中的两个经典分类中的class with pointer member(s),主要内容是Big Three,三个特殊函数。

    我们如何创建String类型的对象:

    1.直接创建;

    2.不直接创建,传入一个已经创建好了的对象作为参数,这种方式就叫做拷贝构造。在创建这个对象的时候,我们会调用与之前所说的(第1点)不同的构造函数,所以,我们要设计一个构造函数的重载;

    3.已经创建好的对象可以进行自由赋值操作,这需要我们创建操作符重载函数来实现这个功能。

    只要是类中有指针成员,就一定要设计拷贝构造函数和拷贝赋值的函数。下面就来谈谈Big

    Three。在C++程序设计里,它是一个以设计的基本原则而制定的定律,三法则的要求在于,假如类有明显地定义下列其中一个成员函数,那么其他二个成员函数也必须一同编写至该类内,亦即三个成员函数缺一不可。

    一.Copy ctor(拷贝构造函数)

    我们一般都不分配固定大小的数组,这样效率太低,我们一般都采取动态分配内存的方式创建字符串,我们不创建数组,而是创建一个指针。如果我们不自己创建拷贝构造函数,对于“b=a;”这样的操作,编译器会默认拷贝,但值得注意的是,系统默认的拷贝是一种“浅拷贝”,会造成内存泄漏,如下图,系统拷贝过来的只是指向目标字符串的指针,并没有完全拷贝内容,只有自己创建拷贝构造函数,才能达到“深拷贝”的效果。

    所谓“深拷贝”,就是先分配跟目标字符串一样大的空间(注意有结束符,所以长度+1),再将来源端拷贝到目的端:

    二.Copy

    assignment operator(拷贝赋值函数)

    跟拷贝构造函数类似,拷贝赋值函数也是先分配空间,再赋值:

    拷贝赋值分为三步:

    1.清空自己;

    2.分配空间;

    3.把来源端拷贝到目的端。

    这里需要注意的是,检测自我赋值非常重要!这一点不仅仅是提高效率,更是为了以后回收正确的内存空间,否则当来源端和目的端本身都指向同一个空间时,delete[]的操作会将这一区域清除掉,造成后续步骤无法操作,如下图:

    三.Destructor(析构函数)

    在创建对象时,会调用构造函数;然而在对象生命结束时,还需要调用析构函数来释放刚才动态生成的空间,否则会内存泄露。

    四.Stack(栈)和Heap(堆)

    栈(stack)——由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。一般,它的空间分配的方式是由系统自动分配。是某作用域scope的一块内存空间(memory space);

    堆(heap)——一般由程序员分配释放,操作系统提供的一块global内存空间,程序可动态分配(dynamic allocate)以获得若干区块(blocks),程序员必须手动释放这些空间!

    五.New和Delete

    New操作:先分配memory,再调用ctor。分为三步:

    1.分配内存;

    2.转型;

    3.构造函数。

    Delete操作:先调用dtor,再释放memory。分为两步:

    1.析构函数;

    2.释放内存。

    六.动态分配所得内存块(memory block)

    1.分配一个复数占用的内存空间

    调试模式下:8+(32+4)+(4*2)=52字节,填补成16的倍数,即为645字节;

    非调试模式下:8+(4*2)=16字节;

    2.分配一个字符串占用的内存空间

    调试模式下:4+(32+4)+(4*2)=48字节;

    非调试模式下:4+(4*2)=12字节,填补后为16字节;

    3.动态分配所得的数组占用空间

    Complex* p=new Complex[3];

    调试模式下:(8*3)+(32+4)+(4*2)+4=72字节,填补后为80字节;

    非调试模式下:(8*3)+(4*2)+4=36字节,填补后为48字节;

    String* p=new String[3];

    调试模式下:(4*3)+(32+4)+(4*2)+4=60字节,填补后为64字节;

    非调试模式下:(4*3)+(4*2)+4=24字节,填补后为32字节.

    可见,我们创建一个复数或者字符串时,系统其实分配了相当大的空间!

    注意:array new一定要搭配array delete,并且在delete数组时一定要加[],否则编译器不知道是数组,只会调用一次析构函数,造成内存泄漏。

    七.一些补充

    1. Static

    在数据或函数之前加上关键字static,成为静态数据或静态函数。静态数据在class之外必须设初值;静态函数只能处理静态数据。调用static函数的方式:

    a.通过object调用;

    b.通过class name调用。

    2. class template(类模板)和function template(函数模板)

    类模板:template

    函数模板:template 编译器会对函数模板进行实参推导(argument deduction)。

    3. namespace

    namespace std.将标准库中的函数包装在一个单元里,编程时就不用写全称了。

    4.C++中还有非常多的细节值得去深入

    相关文章

      网友评论

          本文标题:C++面向对象程序设计(上)第二周学习笔记——Boolan

          本文链接:https://www.haomeiwen.com/subject/feqxcxtx.html