/images/avatar.png

^_^

C++实现XXX

智能指针

 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
61
62
63
64
65
66
67
68
69
#include <iostream>

template <typename T>
class SmartPointer {
public:
    SmartPointer(T* ptr = nullptr) : _ptr(ptr), _cnt(ptr == nullptr ? nullptr : new int (1)){

    }

    SmartPointer(const SmartPointer<T>& other) : _ptr(other._ptr), _cnt(other._cnt) {
        if (_cnt) {
            ++(*_cnt);
        }
    }

    SmartPointer<T>& operator=(const SmartPointer<T>& other) {
        if (this != &other) {
            unpoint();
            _ptr = other._ptr;
            _cnt = other._cnt;
            if (_cnt) {
                ++(*_cnt);
            }
        }
        return *this;
    }

    ~SmartPointer() {
        unpoint();
    }

    T& operator*() const {
        return *_ptr;
    }

    T* operator->() const {
        return _ptr;
    }

    int getCnt() const {
        return _cnt ? *_cnt : 0;
    }

private:
    void unpoint() {
        if (_cnt and --(*_cnt) == 0) {
            delete _ptr;
            delete _cnt;
        }
    }
    T* _ptr;
    int* _cnt;
};

int main() {
    SmartPointer<int> ptr(new int(3));
    std::cout << ptr.getCnt() << '\n';
    SmartPointer<int> ptr2(ptr);
    std::cout << ptr.getCnt() << '\n';
    std::cout << ptr2.getCnt() << '\n';
    {SmartPointer<int> ptr3 ;
    ptr3 = ptr2;
    std::cout << ptr.getCnt() << '\n';
    std::cout << ptr2.getCnt() << '\n';
    std::cout << ptr3.getCnt() << '\n';}
    std::cout << ptr.getCnt() << '\n';
    std::cout << ptr2.getCnt() << '\n';

}

单例

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
class Singleton {
private:
    Singleton() = default;
    static Singleton* instance;
public:
    Singleton(const Singleton&) = delete;
    Singleton& operator=(const Singleton&) = delete;
    static Singleton* getInstance() {
        if (instance == nullptr) {
            instance = new Singleton();
        } 
        return instance;
    }
};
Singleton* Singleton::instance = nullptr;

String

 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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
#include <iostream>

class String {
public:
    String() = default;
    // 构造函数
    String(const char* str) {
        m_size = strlen(str);
        m_data = new char[m_size + 1];
        memcpy(m_data, str, m_size + 1);
    }

    // 拷贝构造函数
    String(const String& s) {
        m_size = s.m_size;
        m_data = new char[m_size + 1];
        memcpy(m_data, s.m_data, m_size + 1);
    }

    // 移动构造函数
    String(String&& s) {
        m_size = s.m_size;
        m_data = s.m_data;
        s.m_size = 0;
        s.m_data = nullptr;
    }

    // 赋值函数
    String& operator=(const String& s) {
        if (this != &s) {
            delete m_data;
            m_size = s.m_size;
            m_data = new char[m_size + 1];
            memcpy(m_data, s.m_data, m_size + 1);
        }
        return *this;
    }

    // 析构函数
    ~String() {
        m_size = 0;
        delete[] m_data;
        m_data = nullptr;
    }

    char& operator[](size_t id) {
        return m_data[id];
    }

private:
    char* m_data = nullptr;
    size_t m_size;
    friend std::ostream& operator<<(std::ostream& os, const String& s);
};


// 重载输出流
std::ostream& operator<<(std::ostream& os, const String& s) {
    os << s.m_data;
    return os;
}


int main() {
    String a = "abc";
    std::cout << a << '\n';
    String b = a;
    b[0] = 'q';
    std::cout << b << '\n';
    String c ;
    c = b;
    c[1] = 'w';
    std::cout << b << '\n';
    std::cout << c << '\n';

    return 0;
}

线程池

 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
61
62
63
64
65
66
67
68
69
70
71
72
73
#include <iostream>
#include <queue>
#include <thread>
class ThreadPool {
public:

    ThreadPool(size_t num_thread = std::thread::hardware_concurrency()) {
        for (size_t i = 0; i < num_thread; i++) {
            threads_.emplace_back([this] () -> void {
                while (true) {

                    std::function<void()> task;

                    // 查看tasks有没有task,或者是否为stop_
                    {
                        std::unique_lock<std::mutex> lock(mutex_tasks_);
                        cv_.wait(lock, [this](){
                            return this->stop_ || !this->tasks_.empty();
                        });
                        if (stop_ && tasks_.empty()) {
                            return;
                        }

                        // 走到这步,队列中一定有任务
                        task = std::move(tasks_.front());
                        tasks_.pop();
                    }

                    task();

                }
            });
        }
    }

    ~ThreadPool() {
        {
            std::unique_lock<std::mutex> lock(mutex_tasks_);
            stop_ = true;
        }
        cv_.notify_all();
        for (auto& thread : threads_) {
            thread.join();
        }
    }

    void enqueue(std::function<void()> task) {
        {
            std::unique_lock<std::mutex> lock(mutex_tasks_);
            tasks_.emplace(std::move(task));
        }
        cv_.notify_one();
    }
private:

    std::vector<std::thread> threads_;
    std::queue<std::function<void()>> tasks_;
    std::mutex mutex_tasks_;
    std::condition_variable cv_;
    bool stop_ = false;
};


int main() {
    ThreadPool tp(3);
    for (int i = 0; i < 5; ++i) {
        tp.enqueue([i]() {
            std::cout << i << ' ' << std::this_thread::get_id() << '\n';
            std::this_thread::sleep_for(std::chrono::microseconds(1000));
        });
    }
    return 0;
}

快排

 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
#include <bits/stdc++.h>

using namespace std;


void quickSort(vector<int>& a, int l, int r) {
    if (l < r) {
        int ptrl = l, ptrr = r;
        int x = a[ptrl];
        while (ptrl < ptrr) {
            while (a[ptrl] <= x and ptrl < r) { // 注意这里是 < r 不是 < ptrr
                ptrl++;
            }
            while (a[ptrr] >= x and ptrr > l) {
                ptrr--;
            }
            if (ptrl < ptrr) {
                swap(a[ptrl], a[ptrr]);
            }
        }
        swap(a[l], a[ptrr]);
        quickSort(a, l, ptrr - 1);
        quickSort(a, ptrr + 1, r);
    }
}

int main() {


    vector<int> a = {3, 5, 1, 8, 9, 4, 2, 6, 0, 1};
    quickSort(a, 1, (int) a.size() - 1);
    for (int i : a) {
        cout << i << ' ';
    }
    return 0;
}

对于顺序的数组,可以先随机洗牌

redis

基础篇

redis命令

通用命令

https://img-blog.csdnimg.cn/direct/7edb39be80224fc9af908caed7424446.png

String类型

https://img-blog.csdnimg.cn/direct/45adff8cd4e54929b431927cfd224774.png

https://img-blog.csdnimg.cn/direct/c1a84a0c6c8c4bc6a300c69d860098b2.png

key的层级结构

e.g.

douyin:user:1

douyin:user:2

douyin:product:1

Hash类型

https://img-blog.csdnimg.cn/direct/d10bc7faa57a4f27ae3131160f40b94d.png

https://img-blog.csdnimg.cn/direct/1d4c3b239ae04cdd987adc882196a78e.png

List类型

https://img-blog.csdnimg.cn/direct/417482b2339e48578d434c83d4302d3f.png

https://img-blog.csdnimg.cn/direct/3d19d9990b5948dab3d83d889018dba1.png

docker2

参考链接

Containerize an application

构建应用的镜像

编写Dockerfile,构建镜像(假设镜像名叫getting-started)

1
docker build -t getting-started .

根据镜像创建容器

C++中继承和虚函数的关系汇总

类C 继承 类B 继承 类A

基类指针指向派生类对象

如果是C->A, B->A,那么操作A和C时,不会触碰到B

析构函数和成员函数之间互不干扰

如果是像这样 B* b = new B 或者 C* c = new C 这种,那构造函数一定会调用基类的,析构函数一定会调用基类的

C++互斥锁

std::mutex

最简单的互斥锁

 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
// mutex example
#include <iostream>       // std::cout
#include <thread>         // std::thread
#include <mutex>          // std::mutex

std::mutex mtx;           // mutex for critical section

void print_block (int n, char c) {
    // critical section (exclusive access to std::cout signaled by locking mtx):
    // mtx.lock();
    for (int i=0; i<n; ++i) { std::cout << c; }
    std::cout << '\n';
    // mtx.unlock();
}

int main ()
{
    std::thread th1 (print_block,50,'*');
    std::thread th2 (print_block,50,'$');

    th1.join();
    th2.join();

    return 0;
}

输出

C++类继承和可见性

三种继承方式,是否真正继承了,子类可访问吗,外部可访问吗

三种可见性,类自己可访问吗,外部可访问吗

继承默认是private继承

继承和可见性问题

private、protected、public

shell三剑客

grep

Global Regular Expression Print

用正则表达式查找文本

grep [-option] {pattern} {file}

-A<行数> 除了显示匹配 pattern 的那一行外,显示该行之后的内容
-B<行数> 除了显示匹配 pattern 的那一行外,显示该行之前的内容
-C<行数> 除了显示匹配 pattern 的那一行外,显示该行前、后的内容
-c 统计匹配的行数
-e 同时匹配多个pattern
-i 忽略字符的大小写
-n 显示匹配的行号
-o 只显示匹配的字符串
-v 显示没有匹配pattern的那一行,相当于反向匹配
-w 匹配整个单词

sed

stream editor

Linux输入输出

万物皆文件 – Linus Torvalds

重定向

标准输入流stdin的文件描述符是0,标准输出流stdout的文件描述符是1,标准错误流的文件描述符是2

标准输入流一般是键盘在终端的输入,标准输出流和错误输出流一般显示在终端屏幕上

mysql

基础

SQL

SQL语言分类

https://img-blog.csdnimg.cn/2afe0b4cdc0245b98d53514141396a15.png

DDL

数据类型

数值型

https://img-blog.csdnimg.cn/1148cd5ca9e743c0a5fe8a5853ab8af6.png

字符串类型

https://img-blog.csdnimg.cn/aa69d47a96fb4404a688d71fdb51c6d9.png

日期和时间型

https://img-blog.csdnimg.cn/5fe2320a10ca4bc0bbfe6ea349d4bec7.png

数据库

查数据库show databases;

查当前数据库select database();