CMU15-445 Lab0 - C++ Primer

Lab0- C++ Primer

个人笔记

代码下载

  1. 按照项目下的文档步骤:

    // 1. 新建一个仓库 bustub-private
    // 2. clone cmu db 远程代码到本地
    git clone --bare https://github.com/cmu-db/bustub.git bustub-public
    cd bustub-public
    // 3. mirror到自己刚创建的远程仓库
    git push --mirror git@github.com:sunshinejiali/bustub-private.git
    // 4. 删除 cmu db 的本地副本
    cd ..
    rm -rf bustub-public
    // 5. 拉取自己的远程仓库代码
    git clone git@github.com:sunshinejiali/bustub-private.git
    // 6. 添加 cmu-db 作为自己的第二远程仓库
    cd bustub-private
    git remote add public https://github.com/cmu-db/bustub.git
    // 7. 验证是否已经添加
    git remote -v
    // result:
    // origin  [email protected]:sunshinejiali/bustub-private.git (fetch)
    // origin  [email protected]:sunshinejiali/bustub-private.git (push)
    // public  https://github.com/cmu-db/bustub.git (fetch)
    // public  https://github.com/cmu-db/bustub.git (push)
    // 8. 提取 cmu-db 中的更改
    git pull public master
    
  2. 使用 2020 年的版本,因此需要回退到之前提交的某一版本。

    // 将代码回退到某一版本,head 指向当前的目标版本,删除之后的所有版本
    git reset --hard 444765a
    // 检查一下是否回退到正确的版本
    git log
    // (强制)提交更改
    git push -f
    
  3. 报错

    • 如果安装工具的时候报这个错误 ,这可能是因为在 windows 下编写好 .sh 文件后,在Linux 下运行报错。

      // 报错
      build_support/packages.sh: line 2: $'\r': command not found
      build_support/packages.sh: line 13: $'\r': command not found
      build_support/packages.sh: line 14: syntax error near unexpected token `$'{\r''
      'uild_support/packages.sh: line 14: `main() {
      
      //解决
      // 使用 vim 打开文件
      vim packages.sh
      // 转换格式
      :set ff=unix
      // 保存文件
      :wq
      
    • make format 报错

      // make format 报错
      /usr/bin/env: ‘python’: No such file or directory
      make[3]: *** [CMakeFiles/format.dir/build.make:57: CMakeFiles/format] Error 127
      make[2]: *** [CMakeFiles/Makefile2:287: CMakeFiles/format.dir/all] Error 2
      make[1]: *** [CMakeFiles/Makefile2:294: CMakeFiles/format.dir/rule] Error 2
      make: *** [Makefile:214: format] Error 2
      
      // 解决:没有python, 安装
      sudo apt-get install python
      
  4. 编译

    mkdir build
    cd build
    cmake ..
    make
    // 测试
    cd ..
    cd build
    make check-tests
    

C++教程

  1. for 循环

    // 使用引用,允许修改数组中的元素。
    for(int& i: someDataStructure) { doSomething();}
    // 显示数组中的值,并保护数组成员,启用按值访问,不允许修改元素。
    for(int i: someDataStructure) doSomething();
    
  2. Lambda 函数的 Lamba 表达式——有主体但没有名字的函数

    • firstPart
      • [] 这意味着不会向 lambda 提供任何东西。
      • [&] 用于表示有一些引用。
      • [=] 用于copy。
      • [this] 用于封装类。
    • secondPart 是无名函数的参数列表所必需的,但它也可以留空。
    • TypeYouReturn 用于注册将从 lambda 返回的类型。
    • BodyOfLambda 用于希望执行的操作,键入一些代码,这些代码将用于执行在此函数主体中应用的操作。
    • acctualParameters 用于向 lambda 函数提供输入。
    // firstPart 用于将在 lambda 函数内部利用的变量范围。
    [firstPart](secondPart) TypeYouReturn{ BodyOfLambda}(acctualParameters);
    
    // 例子1
    double dUpperPart = [](double dX, double dY)double{ return dX*dX +dY*dY;}
    
    // 例子2
    vectror<int> iVector;
    for_each( begin(iVector), end(iVector), [](int n){if(n%2==0)cout<<n<<end;});
    
  3. Static Assertion

    // 两部分:(1)需要判断的表达式。(2)不匹配显示的消息。
    static_assert(evaluatedExpression, stringMessage);
    // 例子
    static_assert(sizeof(long long int)>=16;”This is unexpected”);
    
  4. Move and &&

    // 在类中实现移动构造函数
    MovableClass(MovableClass&&);
    // 需要移动配置的时候,这样调用
    MovableClass&& operator=(MovableClass&&);
    
  5. 指针

    • 用 nullptr 替换 NULL。就像初始化了一个为空的零值。
    • 新类型的智能指针:唯一指针、共享指针、弱指针
      • unique_ptr 是 C++ 的新特性,它将使您能够保护存储在内存中的某些资源的所有权。如果某物拥有所有权,它就不能共享,但它是可移动的。这意味着您可以将其转移到另一个唯一的指针。unique_ptr 的示例将解决异常不安全代码。

        unique_ptr<someType> suniquePtr(new someType(args)); 
        ... 
        uniquePtr.release();
        
      • shared_ptr 顾名思义,它适用于需要共享内存中某些资源的所有权的情况。

        shared_ptr<someType> somePtr(new someType(args));
        
      • weak_ptr 允许访问可能存在于内存中的内容,如果您有占用内存的对象,则授予访问权限,并且可以删除该对象,如果上次使用过,则调用必要的析构函数。

        weak_ptr<someType> weakPtr = somePtr;
        
  6. 统一初始化和初始化列表

    如果希望使用构造函数,最好用 {} 替换旧样式的初始化 ()

    • 初始化

      // 原来的
      CSomeClass SomeObject(argument1,argument2);
      
      // 新版的
      CSomeClass SomeObject={argument1,argument2};
      
    • 添加元素

      // 原来的,已经过时了
      vector <int> ourVector;
      for(int i=0; i<5; ourVector.push_back(i++));
      
      // 新版的
      vector< int> ourVector={0,1,2,3,4,};
      
  7. 构造函数和继承

    • 构造函数,初始化 nSomeValue
    class CSomeClass
    {
    private:
    	int nSomeValue=0;
    ...
    }
    
    • 继承构造函数
    class CChild: public CParent 
    { 
    public: 
    using CParent::CParent   
    }
    
  8. 虚函数

    • 当有继承,需要应用虚方法时,在名字前面写 virtual 就足够了,每次在低级类中有方法时,都会用虚方法进行挖掘。
    • 如果希望防止方法被覆盖,则在方法前面添加 final,然后就无法修改方法的行为方式。
  9. 多线程

    • 当开始线程时,你可以使用:加入、交换、分离、睡眠等。
    • 如果保护某些资源免受其他线程的影响,以便现在获得预期结果,则应该在其库中添加不同类型的互斥锁:互斥锁、递归互斥锁、定时互斥锁和递归定时互斥锁
  10. 编程风格

    auto tuple = make_tuple(“triangle”, ‘t’, 10, 15, 20);
    
    // 将具有一个元素字符串而另一个是向量的映射
    map<string,vector<int>> aMap;
    

GDB教程

  1. 如果想要调试 main 函数。

    gdb main
    // or gdb a.out
    // 运行
    run
    // or start
    // 回溯,看是哪里的问题
    backtrace
    // 查看某个地址处的值, x 可以看作是 examine 的缩写。
    x 0xffbef014
    
    • 查看程序崩溃后的信息。backtrace
  2. 条件和断点

    • 打断点会返回一个编号,方便以后引用断点,例如删除。
    • 仅在 item_to_remove 等于 1 时,在第 52 行中断。
    // 打断点,在第 52 行。
    break LinkedList<int>::remove
    
    // 仅在 item_to_remove 等于 1 时,在第 52 行中断。
    condition 1 item_to_remove==1
    
  3. quit 退出。

  4. 输入 step 可以继续运行,输入 next 将会一步一步向下进行。

  5. ctrl + a 可以展示出一个文档。ctrl + L 可以从输出的显示中恢复到没有输出的显示,恢复正常的显示。q 退出。

实验指导书

  1. 在这个 Project 中,将实现三大类:MatrixRowMatrix,和 RowMatrixOperations。这些矩阵是简单的二维矩阵,必须支持加法、矩阵乘法和简化的 通用矩阵乘法(GEMM) 运算。

  2. 只需要修改一个文件:p0_starter.h 可以在BusTub 存储库中的 src/include/primer/p0_starter.h 中找到该文件。

  3. 在这个头文件中,定义了需要实现的三个类。该 Matrix 抽象类定义了派生类 RowMatrix 常用的功能。该 RowMatrixOperations 课程将使用 RowMatrix 对象来实现概述中所提到的操作。函数和成员变量在文件中指定。项目要求填写所有构造函数、析构函数和成员函数的实现。不要增加任何附加功能的原型或者成员变量。只需要修改我们已提供定义的功能。

  4. 由于有些代码未实现,所以测试文件中有 DISABLED 前缀的参数,用来禁止使用某些测试。所以,当我们实现了应该实现的功能后,可以删除 DISABLED 前缀,用来测试当前函数的功能。

    // For example
    // Original
    TEST(StarterTest, **DISABLED_**MultiplyMatricesTest) {
    	// .... 
    }
    // New
    TEST(StarterTest, MultiplyMatricesTest) {
    	// .... 
    }
    
  5. 本地测试

    // 如果之前建过 build,则直接到 build 下
    make starter_test
    ./test/starter_test
    
  6. 提交测试之前,检查格式问题

    // 在 build 下
    make format
    make check-lint
    make check-clang-tidy
    
  7. 打包提交测试

    • 网址:https://www.gradescope.com 注册 2020 课程代码:5VX7JZ
    zip project0.zip src/include/primer/p0_starter.h
    

知识点

  1. C++动态分配内存数组 https://blog.csdn.net/DumpDoctorWang/article/details/80902947

  2. C++ unique_ptr 智能指针

    • unique_ptr 不共享其指针, 只可以使用 new 来分配内存,又因为 unique_ptr 不可拷贝和赋值,初始化必须使用直接初始化的方式。
    unique_ptr<int> number(new int()); //直接初始化
    // 空的 ptr,使用 delete 释放。
    unique_ptr<int> number;
    // 空的 ptr,使用 d 删除器释放。
    unique_ptr<int,D> number(d);
    // 释放其指向对象
    number = nullptr 
    // 放弃所指对象的控制权,并返回保存的指针,将 number 置为空,不会释放内存
    number.release()
    // 参数可以为空、内置指针,先将 number 所指对象释放,然后重置 number 的值.
    number.reset()
    
    • 它不能复制到另一个 ,按值传递给函数,也不能在需要创建副本的任何 C++ 标准库算法 unique_ptr 中使用。 在某一时刻,只能有一个unique_ptr 指向特定的对象。当unique_ptr 被销毁时,它所指向的对象也会被销毁。因此不允许多个unique_ptr指向同一个对象。

    • 只能 move unique_ptr。 这意味着,内存资源所有权将转移到另一个 unique_ptr,并且原始 unique_ptr 不再拥有此资源。move 是在 中定义的。

      CMU15-445 Lab0 - C++ Primer_第1张图片

    • unique_ptr C++ 标准库的标头中定义。 它的效率与原始指针完全相同,可用于 C++ 标准库容器。 向 C++ 标准库容器添加 实例非常高效,因为 的移动构造函数无需 unique_ptr unique_ptr 复制操作。

    • 不能拷贝 unique_ptr 的规则有一个例外:我们可以拷贝或赋值一个将要被销毁的unique_ptr (C++ Primer 5th p418),可以从函数中返回一个unique_ptr。

      std::unique_ptr<RowMatrix<T>> matrix(new RowMatrix<T>(matA->GetRows(), matB->GetColumns()));
      // 因此这里这样写是没有问题的。
      matrix = MultiplyMatrices(std::move(matA), std::move(matB));
      if (matrix != nullptr) {
        return AddMatrices(std::move(matrix), std::move(matC));
      }
      
    • unique_ptr 参数可以使用引用避免所有权的转移,或者暂时的移交所有权。

    • 用unique_ptr管理非new对象、没有析构函数的类时,需要向unique_ptr传递一个删除器。不同的是,unique_ptr 管理删除器的方式,必须在尖括号中unique_ptr指向类型后面提供删除器的类型,在创建reset 一个这种 unique_ptr 对象时,必须提供一个相同类型的可调用对象(删除器),这个删除器接受一个 T* 参数。

    • 在调用 number.release() 时不会释放 number 所指的内存的,这时返回值就是对这块内存的唯一索引,如果没有使用返回值释放内存或保存,这块内存就泄漏。

Coding

  1. 初始化:

    • 使用 new 初始化 lineardata_
    • 使用 memset 将新创建的数组清零。
    • 创建一个指向 matrixunique_ptr
    std::unique_ptr<RowMatrix<T>> matrix(new RowMatrix<T>(row, col);
    
  2. unique_ptr 的移动:

    MultiplyMatrices(std::move(matA), std::move(matB));
    
  3. 结果:

CMU15-445 Lab0 - C++ Primer_第2张图片

参考资料

  1. unique_ptr的使用和陷阱 https://blog.csdn.net/qq_33266987/article/details/78784286
  2. 如何创建和使用 unique_ptr 实例 https://docs.microsoft.com/zh-cn/cpp/cpp/how-to-create-and-use-unique-ptr-instances?view=msvc-160
  3. 缺少引用请联系。

你可能感兴趣的:(CMU,15-445,学习笔记,c++,git,数据库)