多重指针的理解简介其实这本不是一个很难理解的内容: 指针就是指向一个数据的地址
而所谓的多重指针就是指向指针的指针,反复的嵌套。
指针的值存储着对应类型的地址
背景在实现一个节点数据的移动代码时,仿佛对这个问题有了更新的理解
所有特此记录一下:
1234567891011121314 LRUNode **new_list = new LRUNode *[new_length]; memset(new_list, 0, sizeof(new_list[0]) * new_length); for (uint32_t i = 0; i < length_; i++) { LRUNode *h = list_[i]; // h 指向list连续地址中偏移i个单位的地址 while (h != nullptr) { LRUNode *next = h->next_hash; // next 获取h的下一个节点 uint32_t hash = h->hash; LRUNode **ptr = &new_list[h ...
skills未读
gdb调试CMU15445-P3gdb调试CMU15445-P3简介在小型的项目中,代码流程都很清楚,并没有涉及到复杂的函数调用与层层封装,然而在一个比较完整的项目中,层与层之间的高度封装,函数流的调用,让我们想理解某一块的代码实现增加了许多困难。
为此,使用 gdb 调试代码可以很好的显示中间过程以及调用流,以方便我们更好的理解某一块代码的实现。
本文并不涉及到 gdb 相关的基础语法
基础语法可以参考 GDB调试
准备工作由于在 CMU15445 的 P3 中需要实现几个执行器与优化算子,所以必须要理解此处的代码流程是什么。
当我们运行它所要求的 SQL 语句之后
报错是由于 SeqScanExecutor 没有实现
所以现在应该找到该类所对应的文件
那么该项目是如何执行到这个位置呢?传入参数的含义分别是什么呢?
此时我们就可以通过 gdb 来定位执行流程
如上图, 在使用 gdb 启动项目之后,我们在需要定位的地方打上断点,之后就可以开始调试。
定位流程输入对应的语句
12CREATE TABLE t1(v1 INT, v2 VARCHAR(100));SELECT * FROM t1;
我们发现 ...
理解直接初始化与复制初始化的区别简介当用于类类型对象时,初始化的复制形式和直接形式有所不同:
直接初始化直接调用与实参匹配的构造函数。
复制初始化则是首先使用指定构造函数创建一个临时对象,然后用复制构造函数将那个临时对象复制到正在创建的对象。
很多时候编译器会默认给我们进行优化,省去创建临时对象这一步,以此来节省创建临时对象的损耗。
对比下面的源代码来自于c++拷贝初始化和直接初始化的底层区别
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950#include <cstring>#include <iostream>using namespace std;class ClassTest { public: ClassTest() { c[0] = '\0'; cout << "ClassTest()" << endl; ...
智能指针简介有关内存的分配与释放。我们往往会遇到以下的问题。
由于疏忽忘记释放 new 出来的堆空间。
由于代码逻辑的原因,在 if 判断, try-catch 异常中直接退出函数块,导致并没有执行函数末尾的 delete 逻辑。
智能指针的解决方案 :分配的动态内存都交由有生命周期的对象来处理,那么在对象过期时,让它的析构函数删除指向的内存。
c++11 提供了 unique_ptr、shared_ptr 和 weak_ptr 方便我们去管理内存。
auto_ptr在这里先说一下 c++98 提供的 auto_ptr :
与 unique_ptr 类似,都是对资源的独占性。
但是在 C++11 后 auto_ptr 已经被“抛弃”,具体的原因有以下几点 :
复制或者赋值都会改变资源的所有权 12345678910auto_ptr<string> p1(new string("Hello"));auto_ptr<string> p2(new string("World"));cout << &quo ...
c++ 中左右值与 std::move 的解析简介在 c++ 中,对于拷贝我们经常会遇到以下的问题:
十分影响性能的场景:
程序中存在大量的无用拷贝。
创建许多临时值,先将临时值进行拷贝,之后再将临时值释放。
存在一些对象不能拷贝 : unique_ptr
所以如果存在一种移动逻辑,将一个对象的所有权移动到另一个管理对象,这样就可以避免许多无用的拷贝以及无法拷贝,从而提升性能。
左/右值对移动的探讨,首先需要理解两个概念:左值、右值。
从代码逻辑上判断:左值就是 = 左边的值,即可以取地址,右值就是 = 右边的值,无法取地址。
12int a = 5; // a是左值,5是右值B b = B(); // b是左值,B()是右值
左/右值引用从名字上看左右值引用无非就是对应类型变量的别名,c++引入引用这种语法,本身是想降低对指针的使用难度,因为引用本身是通过指针来实现的,都是为了避免拷贝,直接访问对象。
左值引用左值引用就是对左值的引用,给左值取别名。主要作用是避免对象拷贝。
123int a = 5;int &ref_a = a; // 左 ...
std::tuple简介std::tuple 是类似 pair 的模板。相对于 pair 只含有两个成员,每一个 tuple 实例都可以有不同的成员数目。
tuple 的创建与初始化12std::tuple<T1, T2, TN> t1; //创建一个空的tuple对象(使用默认构造),它对应的元素分别是T1和T2...Tn类型。std::tuple<T1, T2, TN> t2(v1, v2, ... TN); //创建一个tuple对象,它的两个元素分别是T1和T2 ...Tn类型。
这些方式属于直接构造 tuple 对象。同时也可以通过下面的方式创建 tuple 对象。
12345678910auto t3 = std::tie(T1, T2, T3); //返回左值引用的元组auto t4 = std::make_tuple(T1,T2,T3); //创建一个拷贝对象std::get<2>(t3); // 假定 T3 初始为 1T3++;std::get<2>(t3); // T3 变为 2std::get<2> ...