Part1
32位内存大小和对齐
1 2 3 4 5 6 7 8 9 10 11 12 |
class test { public: void (*p)(); long long ll; char c; union { short st; int a; }; virtual void f() = 0; } |
string构造开销对比
1 2 3 4 5 6 7 |
return ""; return std::string(); std::string temp; return temp; return std::move(temp); |
判断一个类有没有虚函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
class cvt1 {}; class cvt2 { public: int a; }; class cvt3 { int a; virtual void f() {} }; template<class T> class cvt_helper : T { virtual void test() {} }; template<class T> bool has_virtualfunc(T&) { return sizeof(T) == sizeof(cvt_helper<T>); } |
1 2 3 4 5 6 |
cvt1 t1; cvt2 t2; cvt3 t3; std::cout << has_virtualfunc(t1) << std::endl; std::cout << has_virtualfunc(t2) << std::endl; std::cout << has_virtualfunc(t3) << std::endl; |
判断链表有没有环
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
bool hasCycle(struct ListNode* list) { struct ListNode* slow = head; struct ListNode* fast = head; while(fast != NULL && fast->next != NULL) { slow = slow->next; fast = fast->next->next; if (fast == slow) { return true; } } return false; } |
Part2
thread
- 调用CreateThread可以创建一个线程内核对象,内核对象创建成功后,系统会给它从进程的地址空间分配空间供线程使用。
- 系统把传给CreateThread的pvParam参数写入线程堆栈的最上端,然后把指定的线程的入口函数的地址,再写到该线程的堆栈里面。
- 每个线程都有自己的CPU寄存器,这个就是线程的上下文,记录了该线程上一次运行时的状态。这些寄存器是被存到了一个CONTEXT结构体里面的,这个结构体本身是存到了线程内核对象里面的。
- 指令指针寄存器
- 堆栈指针寄存器
- 而C++的std::thread对象内部是调用的__beginthread_ex,这个方式内部其实也是调用了CreateThread,因为操作系统知道的唯一的创建线程的方式就是CreateTHread。但是这两个函数是有区别的:
- 会在C/C++运行时库的堆上分配一款空间,叫__tiddata,这个空间的话,会把线程的入口函数的地址,存到这里去。
- 然后在内部调用CreateThread,不会传函数的地址,传的是threadstrartex的地址,threadstartex传过去的是tiddata的地址。退出时先调用endthreadex,为了去销毁那部分tiddata空间。
- 通过TlsSetValue把一个值与主调线程关联起来,就是线程局部存储。
进程同步方式
- 互斥量
- 信号量
- 事件
线程同步方式
- 全局变量
- 互斥量
- 信号量
- 事件
- 临界区
AVL和红黑树
- AVL
- 完全的平衡二叉树,如果有频繁的插入删除的话,会引起频繁的rebalance,所以效率会比较低
- 红黑树
- 弱平衡的平衡二叉树,因为它的节点是受一些限制的,这些限制会保证从根节点到叶子节点的路径中,没有任何一条路径的长度是其他的2倍。
- 所以呢,它的插入最多旋转2次,删除最多旋转3次。相对于AVL的话,效率会比较高。
- 红黑树限制
- 首先每个节点要么黑色的要么是红色的
- 根节点,叶子节点都是黑色的
- 黑色节点的子节点都是红色的
- 任意一个节点到每个叶子节点之间路径,都包含了相同数量的黑色节点
观察者模式
- 建立一种对象与对象之间的依赖关系,一个对象发生改变时将自动通知其他对象,其他对象将做出相应反应。
- 发生改变的对象称为观察目标,被通知的对象称为观察者
- 一个观察目标可以对应多个观察者,而这些观察者之间没有相互联系,可以根据需要增加和删除观察者。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
// 抽象目标 class Subject { public: virtual ~Subject() {} void attach(ObServer* observer) { observer_.push_back(observer); } void detach(const int index) { observer_.erase(observer_.begin() + index); } void notify() { for (auto obs : observer_) { obs->update(this); } } virtual int getstate() = 0; virtual void setstate(const int state) = 0; private: std::vector<Observer*> observer_; }; // 具体目标 class CAetSubject : public Subject { public: ~CAetSubject() {} int getstate() { return state_; } int setstate(const int state) { state_ = state; } private: int state_; }; // 抽象观察者 class Observer { public: virtual ~Observer() {} virtual int getsate() = 0; virtual void update(Subject* subject) = 0; }; // 具体观察者 class CAetObserver : public Observer { public: CAetObserver(const int state): state_(state) {} ~CAetObserver() {} int getstate() override { return state_; } void update(Subject* subject) override { state_ = subject->getstate(); std::cout << "state update " << std::endl; } private: int state_; }; |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
int main() { CAetObserver ob1(111); CAetObserver ob2(222); std::cout << ob1.getstate() << std::endl; std::cout << ob2.getstate() << std::endl; Subject* sub = new CAetSubject(); sub->attach(&ob1); sub->attach(&ob2); sub->setstate(333); sub->notify(); std::cout << ob1.getstate() << std::endl; std::cout << ob2.getstate() << std::endl; return 0; } |
监控进程
本文为原创文章,版权归Aet所有,欢迎分享本文,转载请保留出处!
你可能也喜欢
- ♥ 2022_03_0203/09
- ♥ 2023_02_2002/20
- ♥ 2020_11_2302/17
- ♥ 2020_04_2804/28
- ♥ 2020_11_0511/23
- ♥ 2025_03_1803/18