C++的pImpl——编译防火墙 2022-04-17| C++ | pImpl Pimpl(pointer to implementation, 指向实现的指针)是一种常用的,用来对“类的接口与实现”进行解耦的方法。这个技巧可以避免在头文件中暴露私有细节(见下图 1),因此是促进 API 接口与实现保持完全分离的重要机制。但是 Pimpl 并不是严格意义上的设计模式(它是受制于 C++ 语言特定限制的变通方案),这种惯用法可以看作桥接设计模式的一种特例。
这里的公有类拥有一个私有指针,该指针指向隐藏的实现类
在类中使用 Pimpl 惯用法,具有如下优点:
降低耦合
信息隐藏
降低编译依赖,提高编译速度
接口与实现分离
为了实现 Pimpl,我们先来看一种普通的类的 ...
阅读更多 UML 类图 2022-04-17| UML | UML 类与类之间的关系
实心菱形,代表有东西,has-a,组合/复合关系,composition
空心菱形,代表有东西,但很虚,指针指向,委托关系
空心三角形箭头,子类指向父类,表达继承
下划线,表达静态对象
类图中,+ 代表public,可以不写;-代表私有;#代表protected
阅读更多 侯捷c++面向对象 笔记(四) 2022-04-17| C++ | C++ 面向对象OOP
类与类之间的关系
继承
组合/复合
委托
复合(COMPOSITION 表示has-a)概念理解123456789101112131415template< class T , class sequence = deque<T> >class queue{ ...protected: sequeue c;public: //以下完全利用对象 c 的操作函数来实现 bool empty() const { return c.empty(); } size_type size() ...
阅读更多 侯捷c++面向对象 笔记(三) 2022-04-12| C++ | C++ staticthis数据或函数之前添加,成为静态数据或静态函数
成员函数隐藏参数this,可以直接在成员函数中调用,可以在函数体中出现
静态函数没有this这个隐藏参数,如果要处理数据的话只能处理静态数据
示例12345678910111213141516class Account {public: static double m_rate;//只声明 static void set_rate(const double & x) { m_rate = x; }};double Account::m_rate = 8 ...
阅读更多 侯捷c++面向对象 笔记(二) 2022-04-10| C++ | C++ Class with pointer members拷贝构造与拷贝赋值不写的话编译器会自己生成一份对于包含带指针的成员的类,如果不重写这两个函数,那么去拷贝一个对象时,对于这个对象中的某个带指针的成员,则会完全拷贝原指针,新的对象和老的对象中的这一个指针指向同一个老对象中的成员的地址,这并不是真正的拷贝
深拷贝和浅拷贝浅拷贝:指针拷贝深拷贝:内容拷贝
big three,三个特殊函数:拷贝构造函数、拷贝赋值函数、析构函数当写包含带指针的成员的类时,一定要写这三个函数
Class with pointer members 必须有拷贝构造和拷贝赋值拷贝构造函数拷贝构造的过程,是直接开辟新的内存空间 ...
阅读更多 侯捷c++面向对象 笔记(一) 2022-04-10| C++ | C++ Class without pointer members引用头文件引用标准库头文件使用尖括号<>引用自己写的头文件使用双引号””c++中头文件引用可以省略.h
头文件防卫式声明1234#ifndef COMPLEX_COMPLEX_H#define COMPLEX_COMPLEX_H...#endif //COMPLEX_COMPLEX_H
避免重复include,同一个程序中如果之前已经include之后,再次进来就不会走…的代码了
class的声明有些函数可以直接在头文件的class body内定义,有些在body之外定义
内联函数inline函数在class本体内 ...
阅读更多 堆排序 2021-08-07| 算法 | 算法导论 排序 堆的数据结构和相关性质逻辑结构为一个近似完全二叉树,具有完全二叉树的性质
物理结构为数组
A.length为数组中元素的个数
A.heap-size为存放在数组A中的堆的元素个数
A.length≥A.heap-size
对于某二叉树中的节点i,对应到数组A中的索引位置:
i的父节点为⌊i/2⌋(向下取整)
i的左子节点为2i
i的右子节点为2i+1
注意:这里的乘除2的操作在实际代码中可以使用左移右移操作来提高效率
最大堆:A[PARENT(i)]≥A[i]最小堆:A[PARENT(i)]≤A[i]
只能保证树根是最大的或最小的!!!
最大堆MAX-HEAPIFY维护最大堆的性 ...
阅读更多 深入理解计算机系统——内存 2021-07-20| 深入理解计算机系统 | CSAPP 操作系统 缓存,有层级概念hierarcy,多级缓存理想状态下,指令和存储构成最简单的计算机系统运算功能内存大小限制内存访问速度cpu 算数逻辑单元ALU运算速度单位时间内运算速度有限
所以要1、提高计算速度2、提高I/O速度及对应两种设计理念——计算密集型和IO密集型
听说过迪奥西多城墙么?cpu存在“内存之墙”。cpu运算速度再快,但因为其存在与内存之间IO的耗时,制约运算能力的并不是cpu的算力本身,而是“内存之墙”——内存IO
当前多核CPU成为常态,有一个关键问题需要解决——一致性问题consistency存储在同一块内存里的资源被两个不同的核同时进行处理,需要做状态同步,保持一致包 ...
阅读更多 Leetcode. 链表 2021-07-03| 算法 记住这些:
虚头结点&双指针就能解决大部分问题
舍得用变量,千万别想着节省变量,否则容易被逻辑绕晕
head 有可能需要改动时,先增加一个 假head,返回的时候直接取 假head.next,这样就不需要为修改 head 增加一大堆逻辑了。往往这种时候,cur指针先指在dummynode,然后循环中使用cur>next与cur->next->next,来进行遍历
画出遍历、移动等过程
题目剑指 Offer 06. 从尾到头打印链表
剑指 Offer 18. 删除链表的节点
剑指 Offer 22. 链表中倒数第k个节点
剑指 Offer 24. 反转链表
...
阅读更多 读《重构——改善既有代码的设计》 2021-07-02| 基础能力 | 读书笔记 Tips重构后即运行测试。小步修改,每次修改后就运行测试,每次成功的重构后就提交代码,可以轻松地回滚到上一个可工作的状态。好代码的检验标准就是人们能否能轻易的修改它。软件的性能通常至于代码的一小部分相关,改变其他的部分往往对总体性能贡献甚微。对于重构过程中产生的性能问题,大多数情况下可以忽略它,先完成重构,再做性能优化。编写软件是一个累加的过程,添加新功能最快的方法往往是先修改现有的代码,使新功能容易被加入。当你感觉需要撰写注释时,请先尝试重构,试着让所有的注释都变得多余。编写优良的测试程序,可以极大地提高编程速度,即使不进行重构也是如此。类应该包含它们自己的测试代码。
什么是重构重构不应指代 ...
阅读更多