《Essential C++》读书笔记

来源:互联网 发布:mongodb使用场景知乎 编辑:程序博客网 时间:2024/05/01 18:21

最近想复习一下C++的知识,刚好实验室有一本《Essential C++》,页数比较平易近人,花了两天过了一遍,做了一些笔记。个人觉得里面举得代码不够浅显(很多都是符号重构),让人(尤其初学者)没有想看的欲望,不过复习的话匆匆扫一眼大概也无所谓了。

  1. C++区别于C的一个地方就是加入了引用(reference),其实就是传址,或者更通俗来说就是取别名。如:
    int a=5;int &b=a;
    这样就给a取了一个别名b,a和b有同样的地址,指向于同一块内存。注意和指针的区别:1.指针存的是地址,要加*才能获取到内存里的数据;2.指针可以重新指向别的内存,而引用不可以。
    在函数传递参数的时候推荐使用引用,而不是传值,尤其是参数为对象的时候,引用效率更高,而如果只是读取参数的数据而不进行改动,可以添加const进行限制。如:
    void getData(const classType& para);

  2. template模板
    template<typename T>和template<class T>基本没有区别。
    具体用法参照:template用法

  3. 容器
    顺序容器主要有:Vector, List, Deque
    关联容器主要有:map, set
    之前在网上看到一句话,觉得便于理解这几种容器:vector封装数组,list封装了链表,map和 set封装了二叉树
    接触的比较少的是deque,从名字来看就是双向队列,找了一下资料,发现这是一种介于vector和list的容器,它不像vector只用一块内存,一旦内存不够就要重新申请一块大内存,然后把旧内存里的所有数据都搬过来;它采用的是多个内存,内存之前指针进行连接,好处就是便于扩展,缺点就是遍历比较慢,因为需要内存跳转。从头或尾部插入数据都比较快,而且不会导致迭代器失效,而如果从中间插入或删除数据会导致所有的迭代器都失效(个人觉得应该是部分失效,但是由于多内存存储,无法判断是那部分失效所有干脆说全部失效)。

  4. 构造函数
    如果没有显式地调用基类构造函数(一般在初始化列表中),则自动先调用基类的默认构造函数,再调用自身的构造函数。

    何时需要编写拷贝构造函数?看下面的例子:
    class A{int a;string* b;//指针类型};main(){A obj1;//...A obj2=obj1;}
    当没有编写拷贝构造函数的时候,系统会自动用obj1的数据对obj2进行成员逐一初始化,而类A中有一个成员是指针类型的,这样一来obj1和obj2中的b就指向了同一块内存,一旦有一个对象先析构了,就会释放掉这块内存,那么另一个对象里的b就成了野指针。

  5. 虚函数
    一旦函数被设为虚函数,那么在编译时并不能确定会调用的是基类的还是派生类的函数,而是根据运行时指向的对象类型来选择。
    而如果不是虚函数,则会根据指针或者变量的类型来选择调用函数。

  6. 析构函数
    与构造函数相反,系统会在调用完自身的析构函数之后再调用基类的析构函数。
    一般会将析构函数设为虚函数,除非你的类不会被继承。由于上一条的原因,如果不设为虚函数,用指向派生类对象的基类指针进行析构的时候,调用的还是基类的析构函数,会导致派生类的部分没有被正确地释放。

  7. 如果不希望某个类函数在运行过程中修改到类成员,可以在类函数后面添加const修饰符。如:
    class A{int num;string* name;public:void display() const;};
    这样在编译时一旦发现成员被修改,就会报错。

  8. const int* p; //指向const int的指针
    int const* p;//指向int的const指针

  9. 函数对象
    字面意思就是一个对象能够实现函数的功能,最简单的例子:
    class A{public:int operator()(int x){return x;}};main(){A a;a(5);}
    函数对象使得函数更灵活,一个对象能实现多种功能,比如:
    class lessThan{int m_val;//用来比较的值public:lessThan(int val):m_val(val){}//初始化inline bool operator()(int val)const {return val<m_val;}//括号重载};main(){lessThan lt10(10), lt20(20);int val=18;if(lt10(val)) cout<<"less Than 10"<<endl;if(lt20(val))cout<<"less Than 20";}
    从上面的例子中看出,这样很容易就可以定义出各个比较值不同的函数对象。

    面向对象的两个重要的特性:继承与多态。

0 0