CMU15445 C++ Primer

前置准备工作

sudo apt install clangd clang-format cpplint

vscode 插件 clangd, Clang-Format, C/C++, C/C++ Extension Pack,CMake

代码格式化与检查

make check-format -j$(nproc)
make format
make check-lint -j$(nproc)
make check-clang-tidy-p0 -j$(nproc)

Task 1

实现 Get, Put, Remove

所谓的 CopyOnWrite 实际上就是可持久化数据结构,类似主席树。每次 Put 新创建 logn 个节点

智能指针的转换

我有一个std::shard_ptr<cost TrieNode>的指针,需要用这个去遍历整个字典树,当找到那个值的时候,节点类型需要向TrieNodeWithValue<T>转换

std::shard_ptr<cost TrieNode> cur(root)
// ...
auto newcur = std::dynamic_cast_pointer<const TrieNodeWithValue<T>>(cur);
// auto newcur = std::dynamic_cast_pointer<TrieNodeWithValue<T>>(cur); 这样做会报错

创建一个智能指针

std::shared_ptr<TrieNode> ptr(std::move(root_.Clone()));
auto temp = root_.Clone();
std::shared_ptr<TrieNode> ptr2(temp);

这样做编译器也会报错。但是下面这样就是ok的

std::shared_ptr<TrieNode> ptr3(root_.Clone());
auto temp = root_.Clone();
std::shared_ptr<TrieNode> ptr4(std::move(temp));

remove 的实现

有很多细节,比如

  1. 删除的时候直接修改一个TrieNode的标志is_value_node_,这个感觉不太好
  2. 如果有某种策略,当访问一个结点时,知道以它为根的子树里面没有一个结点是有值的结点,那么就可以把这个子树给删除,这应该是一个优化的点。
  3. 分情况
  • 根为空
  • 删除根
  • 需要删除的结点的is_value_node_false

Get 的实现

  1. Get 第三条,如果模板参数类型和实际存储的数据类型不匹配的问题,一开始我是用了一个shared_ptr<TrieNode>去遍历,知道找到那个TrieNodeWithValue,但是我需要检查当前的模板参数类型 T 和 实际上这个参数类型匹配不匹配,一开始想用 typeid().name(),尝试了很久不成功,突然想到dynamic_pointer_cast
    就比如我有一个基类,然后有一个模板派生类,现在模板派生类有一个独有的参数是模板参数类型,现在我有一个基类指针指向一个不知道具有什么样模板参数类型的一个实例,现在我有一个派生类实例且模板参数是 int,我要检查这两个实例类型相不相同怎么做。下面是一个例子
class Base {
 public:
  virtual void f() {}
};

template <typename T>
class Derive : public Base {
 public:
  T a;
  virtual void f() {}
};

int main() {
  // assume we don't know the type of the string
  std::shared_ptr<Base> ptr1 = std::make_shared<Derive<string>>();

  std::shared_ptr<Base> ptr2 = ptr1;

  // now I want to check the type of instance that ptr1 points to,
  // actually is Derive<string>, I want to know if this equals to Derive<int>

  // just use dynamic_cast!
  auto temp = std::dynamic_pointer_cast<Derive<int>>(ptr2);
  if (temp) {
    std::cout << "have same type" << std::endl;
  } else {
    std::cout << "mismatch, conversion fail" << std::endl;
  }
  return 0;
}
// mismatch, conversion fail

task 2

对 root 加上一个锁,避免对树根做了更改。

task 3

It is possible that your environment produces different random numbers than the grading environment.
In case your environment is producing different set of random numbers than our grader, replace your TrieDebugger test with:

auto trie = Trie();
trie = trie.Put<uint32_t>("65", 25);
trie = trie.Put<uint32_t>("61", 65);
trie = trie.Put<uint32_t>("82", 84);
trie = trie.Put<uint32_t>("2", 42);
trie = trie.Put<uint32_t>("16", 67);
trie = trie.Put<uint32_t>("94", 53);
trie = trie.Put<uint32_t>("20", 35);
trie = trie.Put<uint32_t>("3", 57);
trie = trie.Put<uint32_t>("93", 30);
trie = trie.Put<uint32_t>("75", 29);

// Put a breakpoint here.

judge result

compile and run

  1. 提示遇到了内存泄漏(LeakSanitizer)的问题,但是没有提示具体位置,通过在命令行中设置一个命令(LSAN_OPTIONS=verbosity=1:log_threads=1
  2. "!! We recommend that you use clang-14 for developing BusTub. You're using xxx, which is not clang.",不确定如果不管这个问题直接提交会不会有影响。通过在 bustub 根目录下 CMakeLists.txt 中设置自己的 clang 路径就行
add below two lines into CMakeLists.txt, run make 
# set(CMAKE_C_COMPILER "/usr/bin/clang-14")
# set(CMAKE_CXX_COMPILER "/usr/bin/clang++-14")

mkdir build
cd build
cmake ..
make -j 4 # 加速

ref

  1. https://15445.courses.cs.cmu.edu/spring2023/project0/
  2. https://www.cnblogs.com/alyjay/p/16698477.html
posted @ 2023-04-25 14:43  o0yo  阅读(293)  评论(0)    收藏  举报