CMU15445 C++ 学习笔记 - 其一(Project 0)
换设备了之后 hexo 源文件丢失了,笔者竟然忘记(没意识到)可以在 github 仓库里新开一个 hexo branch 存放源文件。
前言
这篇文章里写好的注册课程提交课程流程笔者就不写了。
CMU 15-445/645 (Spring 2023) Database Systems 通关指北
笔者想学 C++ 但找不到做完会有成就感的项目所以一直耽搁着没学,Modern C++ 的名声在外让笔者同样畏惧。虽然笔者看了许多 C++ 的源码也学会了不少语言,但是 Modern C++ 这座大山一直没敢爬,这是本科的情况。
所以,在研究生的第一年,趁还有三年可供摆烂的时间,开始攀登这座大山。
当头一棒捏
Project 0
笔者做的是 2023 年 Fall 的课程,要是笔者能坚持下去的话,大概能和 CMU 的同学们同一时间完成它。
P0 的题目是手写 Trie 树以及利用 Copy-On-Write 让 Trie 树可以同时被多个 Reader 和一个 Writer 访问,这个在原理实在算不上难。让笔者头疼的是 Modern C++ 的语法。现记录如下,可供有一点基础(指除编程外的各科目知识)但也不是完全懂的后来者(大家都是半吊子)参考。
关于 TrieNodeWithValue 的 Clone 函数
按题目要求,在各种赋值的地方应尽量使用 std::move 函数进行所有权变化。首先说明一下 std::move 函数作用:
1 | string s="123"; |
如上所示,当变量传入 std::move 后,在这之后调用该变量将得到一个空值,换言之,该变量被 move 走了。再说一说有类的成员变量的情况:
1 | class A{ |
可以看到,即使是类的成员变量仍然是可以被 move 走的,无论是外部通过 aa->s 的形式,还是内部调用 s,s 最终都会变为一个空值。这是基础。
现在来看 P0 给出的代码:
1 | class TrieNode { |
TrieNodeWithValue 的 Clone 函数返回了一个 unique_ptr 指向一个新创建的 TrieNodeWithValue 类,我们不妨称原类为类 A,类 A.Clone() 返回的为类 B,类 B 是使用 TrieNodeWithValue(std::map,std::shared_ptr) 这个构造函数进行初始化的,这个构造函数本身又调用了父类 TrieNode(std::map) 进行初始化。
这里的赋值都使用了 std::move 语义,至少笔者之前是这么认为的,所以按照 std::move 的作用,类 A 所有的成员变量都应该已经被 move 走了,换言之,类 A.Clone() 了后,类 A 的所有成员变量都访问不到了。这当然是不行的,毕竟 Clone 函数就不包含这种意思。
笔者冥思苦想(如何询问万能的 ChatGPT),终于找到了问题所在。
事实上,在
1 | auto Clone() const -> std::unique_ptr<TrieNode> override { |
这句代码中的 std::make_unique
看上去很麻烦,但也没办法。那么这段代码中的其他 std::move 起到一个什么作用呢?自然就是真正的节省内存了,毕竟无论是 std::map 还是 value 本身,=赋值操作也都是值复制,这里不使用 std::move 应该也没什么问题,就是内存开销大点,过了构造函数那块内存自然就被释放掉了,主要还是课程本身限制必须使用 std::move。