Project 0
Foreword
做的是2023 spring的版本,只会C with STL的人有难了
dynamic_cast
如果指向的对象(*pt)的类型为Type或是从Type直接或间接派生而来的类型,运算符将返回对象的地址,否则返回一个空指针
1 | dynamic_cast<Type *>(pt) |
std::shared_ptr
能够记录多少个shared_ptr共同指向一个对象,从而消除显示的delete调用,当引用计数变为零的时候将对象自动删除
1 | std::shared_ptr<int> p1 = std::make_shared<int>(10); |
std::unique_ptr
独占的智能指针,禁止其他智能指针与其共享同一个对象,从而保证代码的安全
1 | std::unique_ptr<int> p1 = std::make_unique<int>(10); |
std::weak_ptr
std::shared_ptr仍然存在着可能无法释放资源的问题
比如经典的循环引用
1 | struct A; |
解决方法就是把一个std::shared_ptr改成std::weak_ptr
1 | struct A; |
主要是用于检查std::shared_ptr是否存在
右值引用
左值:表达式后依然存在的持久对象
右值:表达式结束后不再存在的临时对象
纯右值:不是将亡值的右值
将亡值:即将被销毁,却能够被移动的值
1 | std::vector<int> foo() { |
要拿到一个将亡值,就需要用到右值引用:T &&
其中 T 是类型,右值引用的声明让这个临时值的生命周期得以延长
只要变量还活着,那么将亡值将继续存活
移动语义
std::move本身只是起到类型转换的作用,把左值转换成右值引用
是移动构造函数或移动赋值符的内部实现进行移动(交换指针、重置原对象等)
1 |
|
std::string_view
提供对std::string的只读视图,本身不持有数据,用于只读函数,性能更好
Task1
实现支持单线程操作的可持久化Trie
Get
沿key遍历路径,利用dynamic_cast判断终点是否确实是值节点
Put
遍历key,若当前字符的路径存在,clone一个node,否则创建一个node
遍历到倒数第二个字符的时候,特殊处理最后一个字符对应的node是否存在
如果不存在,新创建一个值节点,否则用已有节点的children_和value创建一个值节点
Remove
递归地删,写一个辅助函数形如dfs(root, index)
当index == key.size()时,到达递归出口,如果这个节点没有孩子,直接返回nullptr说明删掉就好,否则return没有值的node,保留children_
自下往上地判断要不要把每一个节点删掉就好了
Task2
实现支持并发操作的可持久化Trie
并发场景是多reader单writer
get照伪代码写,put和remove对于写操作开大锁就好了
Task3
debug能力测试
用vscode的可视化debug就能直接看出前两个答案
第三个可以先用vscode的可视化找到需要的节点地址
然后在vscode的debug console里直接用类型强转命令比如
1 | -exec p *(TrieNodeWithValue<unsigned int>*)0x608000000630 |
然后再通过这个东西的value_ptr的地址得到真实值
1 | -exec print *($1.value_.get()) |
Task4
实现大小写转换逻辑,注册到sql层