C++知识点

C++编译原理
    Preprocessing + Compilation + Assembly + Linking
    -E 预编译 生成.i文件
    -S 预编译+编译 生成.s文件
    -c 预编译+编译+汇编 生成.o文件
    -l
    -g 生成调试时间
    -W 使能警告
    符号表
    internal链接属性
        const全局变量
        static变量
        inline
        class类内定义
https://zybuluo.com/uuprince/note/81709
http://lxwei.github.io/posts/262.html


变量的初始化
    全局变量的初始化顺序
        同一个编译单元内的全局变量,初始化的顺序与他们声明的顺序是一致,销毁的顺序则相反
        对于不同编译单元间的全局变量,c++ 标准并没有明确规定它们之间的初始化(销毁)顺序
        解决方案
            Construct On First Use
            引用计数
    http://www.cnblogs.com/catch/p/4314256.html
    thread_local
        每个线程开始时进行初始化
        各个线程独自拥有这个变量
        errno变量其实就是个thread_local的例子


引用与指针
    语言层面上,引用不是指针,只是变量的别名
    从底层实现上,引用是指针实现的


顶层const与底层const
    底层const--const int *ptr; 可以改变ptr,指向类型为const int *
    顶层const--int * const ptr; 不可以改变ptr,指向类型为int *


函数指针与指针函数
    函数指针的本身是一个指针,指针指向的是一个函数
    指针函数的本身是一个函数,其函数的返回值是一个指针
    “*”的优先级低于“()”的优先级


父类指针与子类指针
    父类指针可以指向子类指针,但只能访问父类方法
    子类指针也可以指向父类对象,前提是必须要做类型转换
    如果子类隐藏了父类方法,调用的方法版本由指针类型决定(与虚函数正好相反,虚函数由对象类型决定)
    https://blog.csdn.net/u010355144/article/details/45115321


覆盖与隐藏
    覆盖
        函数参数都相同
    隐藏
        函数相同
        父类中所有同名函数都会被隐藏
        调用被隐藏函数
            object.Base::func
            using Base::func


多态三要素
    父类中有虚函数。
    子类覆盖父类中的虚函数
    通过己被子类对象赋值的父类指针,调用该虚函数
    作用:
        隐藏实现细节
        接口重用


虚函数与多态
    虚函数的特性:动态绑定(只能由引用或指针触发)
    多态:
        1. 引用或指针的静态类型与动态类型不一致
        2. 由动态类型决定真实执行的版本
    override与final
        override 标记此函数覆盖了基类的虚函数(避免发生隐藏),也只有虚函数可以覆盖
        final 标记子类不可以覆盖此虚函数
    默认实参:使用引用或指针的静态类型,而不是动态类型
    绕过动态绑定:使用作用域运算符
    不能设为虚函数的有:
        1. 构造函数(构造函数的顺序,先构造父类)
        2. inline成员函数(不存在函数调用,编译期确定方法内容)
        3. static成员函数(没必要)
        4. 友元函数(没有继承的概念)
    private与virtual
        子类拥有父类的完整拷贝,private只是阻止子类直接访问父类的实现
        private与virtual没有任何关系


虚函数表
    虚函数表是一块连续的内存,每个内存单元中记录一个JMP指令的地址
    每个类都会维护一张虚表,编译器根据类的声明创建出虚表
    对象被构造时,虚表的地址就会被写入这个对象内存的起始位置(保证性能)
    虚函数表将被该类的所有对象共享
https://songlee24.github.io/2014/09/02/cpp-virtual-table/
https://blog.csdn.net/haoel/article/details/1948051


菱形继承
    出现二义性问题直接报错
    这是class-type语言中一种天生的缺陷,由虚继承解决


三/五法则
    如果一个类需要析构函数,那么也需要拷贝构造函数和拷贝赋值构造函数。
    如: 析构函数中需要释放一个构造函数中分配的动态内存,默认的拷贝会使得所有对象都指向同一个动态内存。


内存泄露
    definitely lost:
        1. 多态中,父类的析构函数不是虚函数
        2. 智能指针,循环引用(weak解锁)
        3. 内存覆盖,strncpy
    indirectly lost:
        1. longjmp
    possibly lost:
        1. 由于抛出异常导致没有释放内存


(char *) 0 、(char *) 9 :
    (char *) 0:C语言中,produce a null-pointer value of type char *;其他语言可能执行其他地址
    (char *) 9:大多数语言中执行地址9


宏定义的作用域: 
    C语言标准中宏定义的作用域:
        从定义位置开始,到其当前所在作用域结束,即宏定义只属于当前这个文件,其他文件如果没有通过#include包含这个文件,那就不能使用这个宏定义
        宏定义作用域不受函数等作用域影响


std::atomic与std::memory_order
    六种memory_order
        relaxed:没有顺序一致性的要求,也就是说同一个线程的原子操作还是按照happens-before关系,但不同线程间的执行关系是任意
    https://www.zhihu.com/question/24301047
    https://en.cppreference.com/w/cpp/atomic


内存屏障:
    保证屏障前后的执行顺序
    http://www.cnblogs.com/Mainz/p/3556430.html


volatile:
    与const类似,可以实现类似底层const、顶层const的功能
    作用:
        1. 不允许被优化(具体的内容和机器相关,通常不允许寄存器访问)
        2. 于序列上在另一个对 volatile 对象的访问之前,只适用于单线程
    volatile 只在三种场合下是合适的:
        1. 和信号处理(signal handler)相关的场合
        2. 和内存映射硬件(memory mapped hardware)相关的场合
        3. 和非本地跳转(setjmp 和 longjmp)相关的场合
https://liam0205.me/2018/01/18/volatile-in-C-and-Cpp/


SegmentFault:
    enable: ulimit -c unlimited
    save path: /cores/


new | operator new | placement new
    new
        操作符
        分配足够的空间,并调用相关对象的构造函数
    operator new
        函数
        只分配所要求的空间,不调用相关对象的构造函数
        支持new_handler
    placement new
        重载 operator new 的一个标准、全局的版本
        在一个已经分配好的内存中(栈或者堆中)构造一个新的对象
https://www.cnblogs.com/luxiaoxun/archive/2012/08/10/2631812.html


序列式容器
    array
        静态空间,大小固定
    vector
        动态空间
        每次容量不足,则扩充至两倍;如仍然不足,则扩充至足够大的容量
        每次容量扩充,都会进行内存拷贝
    list
        环状双向链表,尾端以一个空白节点标示
    forward_list
        与list主要在迭代器上的区别
    dequeue
        双向开口,逻辑上连续的线性空间
        动态地以分段连续内存组合而成,内部维护各个分段
容器配接器
    stack
        无iterator,不允许遍历
        默认以deque实现
    queue
        无iterator,不允许遍历
        默认以deque实现
    priority_queue
        无iterator,不允许遍历
        max-heap实现,默认以vector表现为一个完全二叉树
关联式容器
    set
        基于RB-tree实现
        key即value
        不支持写入操作
    multiset
        同set,支持重复键值
    map
        基于RB-tree实现
        基于pair管理
    multimap
        同map,支持重复键值
    unordered系列
        基于hash实现
http://en.cppreference.com/w/cpp/container


智能指针
    默认初始化为空指针
    unique_ptr
        不能拷贝或赋值,但将要被销毁的指针除外
        可以通过release或reset转移指针所有权
    删除器导致shared_ptr和unique_ptr的区别
        shared_ptr的删除器指针是运行时绑定;
        unique_ptr的删除器指针是编译时绑定;
    shared_ptr与control block
        1. 对象指针
        2. 两个引用计数(shared/weak)
        3. 删除器
        4. 配置器
        支持原子访问
        weak_ptr也会保持control block不被释放
https://heleifz.github.io/14696398760857.html
https://en.cppreference.com/w/cpp/memory/shared_ptr


仿函数
    不是函数,但可以像函数一样调用对象(重载了operator())



refs:
    Makefile             https://seisman.github.io/how-to-write-makefile/introduction.html        

 

posted @ 2018-05-10 21:39  SHAEL_BLOG  阅读(183)  评论(0编辑  收藏  举报