自定义博客皮肤VIP专享

*博客头图:

格式为PNG、JPG,宽度*高度大于1920*100像素,不超过2MB,主视觉建议放在右侧,请参照线上博客头图

请上传大于1920*100像素的图片!

博客底图:

图片格式为PNG、JPG,不超过1MB,可上下左右平铺至整个背景

栏目图:

图片格式为PNG、JPG,图片宽度*高度为300*38像素,不超过0.5MB

主标题颜色:

RGB颜色,例如:#AFAFAF

Hover:

RGB颜色,例如:#AFAFAF

副标题颜色:

RGB颜色,例如:#AFAFAF

自定义博客皮肤

-+
  • 博客(108)
  • 收藏
  • 关注

原创 2023 腾讯暑期实习申请经验分享

这篇文章也是给还没有接触到实习和工作的同学们分享一下我申请腾讯实习的 Timeline 和经验,以下仅以我了解的校招技术岗来讲。

2023-04-18 23:51:06 6191 7

原创 【CMU15-445数据库】bustub Project #2:B+ Tree(下)

Project 2 最后一篇,讲解 B+ 树并发控制的实现。说实话一开始博主以为这块内容不会很难(毕竟有 Project 1 一把大锁摆烂秒过的历史x),但实现起来才发现不用一把大锁真的极其痛苦,折腾了一周多才弄完。本文分基础版算法和改进版算法两部分,基础版算法部分我就只讲实现的一些要素,改进版算法再放重要代码,避免两个版本的代码引起混乱。由于加了并发控制后代码改变的位置比较多,我这里贴的截图不能覆盖到所有,如果需要源码可以评论区或私信联系。

2023-03-05 20:47:31 4955 55

原创 【CMU15-445数据库】bustub Project #2:B+ Tree(中)

本篇继续讲解 Project 2:B+ 树的实现。让我们先从相对简单的迭代器实现开始,然后讲述删除的实现。因为删除部分篇幅较长,并发控制我们放到下一篇再讲。

2023-02-21 23:16:29 2967 28

原创 【CMU15-445数据库】bustub Project #2:B+ Tree(上)

Project 2 要实现的是数据结构课上都会讲的一个经典结构 B+ 树,但是相信大多数的同学(包括博主)当时都没有自己动手实现过它,本节就是一个很好的锻炼机会。

2023-02-17 18:00:08 4223 16

原创 VirtualBox Ubuntu 16.04 磁盘不相邻分区扩容解决方案

做期末大作业时用到 VirtualBox 6.1 安装的 Ubuntu 16.04 LTS 虚拟机,开始只分配了 20GB 硬盘,跑实验时发现空间不够,需要对磁盘扩容,折腾了半天,在此做一个小记录。警告:博主并不精通 Linux,具体操作方法都是我在网上搜索的,虽然这里提供的方案包括了备份步骤,但磁盘分区总体来说是很危险的操作,不保证百分百安全。关闭虚拟机,在 VirtualBox 控制台中,点击左上角 管理 —— 虚拟介质管理。找到需要扩容的磁盘,拖动滑条,更改磁盘最大容量。我这里将原来的 20G

2022-12-06 16:10:19 1690

原创 【CMU15-445数据库】bustub Project #1:Buffer Pool

Project 1 共需完成三个任务:可扩展哈希表(Extendible Hash Table)、LRU-K 置换策略(LRU-K Replacement Policy)以及缓冲池管理(Buffer Pool Manager),其中缓冲池的实现会用到前两个,建议就按文档给的顺序实现。关于代码,首先这里主要就是我个人的一个记录空间,文章也就一两百访问量还是中文,不会真有 CMU 学生来看吧(况且写这篇时也早已过了 DDL)。其二,我比较想展示一些具体实现上比较符合 C++ 的代码风格。另外,我对做这种项目时不

2022-11-09 23:54:09 6399 43

原创 【CMU15-445数据库】bustub Project #0:Trie 树实现(C++ Primer)

第 0 个 Project 名为 C++ Primer,目标是实现一个字典树(Trie),内容不难,主要是测试参与者的 Modern C++ 编程水平,对于选课的 CMU 学生如果感觉比较吃力可能就要劝退了。本节要实现的内容全部在文件中。字典树(Trie)是一种有序的树形结构,能够存储键值对并高效地进行前缀匹配,详细介绍可以自行百度。例如插入两个键值对("ab", 1)和,则形成下图的结构:root 是根节点,不存储键;a 是一个非终结节点,只存储键;

2022-10-27 16:40:28 5058 5

原创 【CMU15-445数据库】bustub 项目介绍及环境配置

突然想起来之前一直想做的 CMU 15-445 课程的 2022 Fall 学期开课了,所以决定把 Pintos 项目先放一放,开个新坑跟着 CMU 同步把这个项目做了。

2022-10-27 10:43:28 5954

原创 【UCB操作系统CS162项目】Pintos Lab2:用户程序 User Programs(下)

在上节中,我们已经完成了 Lab 2 要求的参数传递和系统调用中的 halt, exit 以及向 stdout 输出的 write,最终停在了 wait 的实现之前。本节就先从 wait 和 exec 继续。

2022-10-06 20:58:27 2910 1

原创 【UCB操作系统CS162项目】Pintos Lab2:用户程序 User Programs(上)

本节 Lab 2 复杂度有所上升,考虑到文章太长影响观感且有些劝退,博主决定拆成上下两部分来写╰( ̄▽ ̄)╭以下内容大部分都是博主自己的理解,因为本节开始网上能参考的代码明显变少了(很多文章都在解释同一个作者的代码),所以博主也不能保证文章完全正确,如有问题欢迎交流!

2022-09-20 22:50:20 4060 2

原创 【UCB操作系统CS162项目】Pintos Lab1:线程调度 Threads

开始之前如文档所述,在开始编写代码之前需要先阅读掌握 GETTING STARTED 部分和附录中 Code Guide 部分的前四节(重点是 Synchronization)、4.4BSD Scheduler 部分以及 C Standards 部分内容。

2022-09-11 21:46:28 4256 1

原创 【UCB操作系统CS162项目】Pintos Lab0:项目上手 (Getting Real)

Stanford 的 CS144 计网完成后让我们继续挑战一项更难的课程 Lab:UCB 的操作系统 CS162。老规矩讲课部分因为本科基本都学过就略过了。继续安利CS自学指南,和博主同届甚至就住在楼下的大佬的自学网站,汇总了很多国内外高校 CS 相关的高质量公开课。项目内容为理解一个微型操作系统 Pintos 的原理并为其添加几方面的重要功能,有自动化测试样例。PintosBook。

2022-09-10 17:25:29 5331 8

原创 【斯坦福计网CS144项目】Lab5: NetworkInterface

广播一个ARP请求,该IP的主机收到请求后产生ARP回复,告知自己的MAC地址,源主机收到回复记录该对应关系形成ARPcache。如果为ARP,记录源主机的IP和MAC地址映射关系,如果查询的IP地址是自身,则产生ARP回复。对应的MAC地址不知道,就要用上面所说的ARP协议,广播ARP请求并将IP数据报暂存。网络层IP地址与链路层MAC地址存在对应关系,当源主机不知道一个IP数据报的目标IP地址对应的MAC地址时,应该通过。...

2022-07-31 11:15:23 1229

原创 【斯坦福计网CS144项目】Lab4: TCPConnection

在实现了接收端的 TCPReceiver 类和发送端的 TCPSender 类后,本节实验实现掌管这两个类,向用户提供一个完整的 TCP 连接抽象的 TCPConnection 类。正如讲义标题所写,完成本节的实验后,我们是真正攀登上了一个高峰(summit),也是完成了本门课程最重要精华的部分。事前提醒,本节的测试量非常大,其中会用你的 TCP 实现与 Linux 的 TCP 实现进行各种条件的交互,之前的 Sender 和 Receiver 类在实现上如果有潜在问题也都会被暴露出来。所以,如果你在尝试自

2022-07-05 18:34:21 1493

原创 【斯坦福计网CS144项目】Lab3: TCPSender

本节进行 TCP 协议中发送端 TCPSender 的实现。Sender 拥有一个输入的 ByteStream,代表用户提供的待发送的数据,而 Sender 要负责将其组装成 TCP 数据包并发送出去。所谓发送,就是将数据包 push 到一个队列 中即可,下一节实现的 TCPConnection 类(也就是 Sender 和 Receiver 的所有者)会负责从该队列中取走数据包并实际发出。除了保证 TCPSegment 中数据、序号以及 SYN,FIN 等标识设置正确,Sender 主要还需要考虑两个问

2022-07-04 23:01:37 718

原创 【斯坦福计网CS144项目】Lab2: TCPReceiver

本节在 Lab1 实现的 StreamReassembler 的基础上进行 TCP 协议中接收端 TCPReceiver 的实现。Lab 1 中实现的核心函数 认为输入的数据索引是一个 64 位表示(),从 0 开始依序增大的数字。然而 TCP 的序号并非如此:为此,讲义中给出了 seqno, absoulute seqno 和 stream index 的概念,下面这张图可以很好解释各自的含义:后两者的区别仅为相差 1,主要的问题就是如何实现从 seqno(TCP 包携带)到 stream ind

2022-06-22 12:20:17 1067

原创 【斯坦福计网CS144项目】Lab1: StreamReassembler

本节实现的类是 StreamReassembler,即字节流碎片的重组器。我们知道网络环境是不可靠的,其中传输的数据包既不保证不丢失,也不保证按发送顺序到达,因此需要有一个工具负责将这样乱序碎片化到达的流重组成按正确顺序连续排列的数据。重组的依据就是 TCP 协议规定的序列号,即每个字节的数据都有一个独特的编号,数据包会在包头中带上本包第一个字节数据的编号(和数据的长度),以表示本包的数据在整个流中的位置。在后面几节更上层的类的实现中会讲到,这个序列号叫做 seqnum,我们也要自己负责在发送数据时维护它,

2022-06-09 17:39:48 1321 1

原创 【斯坦福计网CS144项目】环境配置 & Lab0: ByteStream

前言感觉学了不少 C++ 编程的知识和技术但比较缺少实践,于是打算找一些项目跟着做一做。首先安利一个自学网站 CS自学指南,北大的同学做的,汇总了很多国内外高校 CS 相关的高质量公开课,其中大部分是有课程项目的。翻了翻感觉 Stanford 的这门 CS144 计网课的 Lab 比较有趣,难度也不错,就是它了!课程网址:CS 144: Introduction to Computer Networking我跟的是 2021 Fall 学期的版本。准备工作在上面的网站中先把 8 个实验的文档(

2022-05-27 23:15:00 7283 8

原创 《Effective Modern C++》学习笔记 - Item 42: 考虑使用emplace代替插入

为容器添加元素时,我们自然想到的是使用 插入(insertion) 函数,包括 push_back,push_front,insert等。但是如果你追求极致的性能,那么这样做可能不是最优的。考虑下面的情况:class MyString {public: MyString() : str("default string.") {} MyString(const char* pc) : str(pc) { cout << "MyString: from st.

2022-04-05 23:00:22 1056

原创 《Effective Modern C++》学习笔记 - Item 41: 考虑对一定会被拷贝,并且移动开销小的参数按值传递

有些函数的参数从设计上就是要被 “拷贝” 的,例如将参数拷贝加入类的容器中,具体可能是通过拷贝或移动的操作实现。为了效率,一般应该对左值参数做拷贝,右值参数做移动,例如下面的代码:class MyString {public: MyString() : str("default MyString.") {} MyString(const MyString& rhs) : str(rhs.get()) { cout << "MyString: co.

2022-04-03 22:29:50 908

原创 《Effective Modern C++》学习笔记 - Item 40: 对于并发使用std::atomic,对于特殊内存使用volatile

std::atomic<T> 类型和 volatile 的功能完全不同,前者应该被用于实现并发的原子操作,而后者应该用于存储在特殊内存中的对象。std::atomic<T> 模板的实例化对象保证对该对象的操作对于所有线程都是原子的,表现如同受 mutex 保护一样(但是实现上一般会使用比 mutex 更底层高效的机器指令),例如:std::atomic<int> ai(0); // initialize ai to 0ai = 10; // ..

2022-04-03 13:46:41 767

原创 《Effective Modern C++》学习笔记 - Item 39: 考虑使用void future实现单次事件通信

本节是一个小技巧,告诉我们可以使用 void 型的 future 实现线程间一次性的事件通信。如何实现两个线程间事件的通信?(例如,副线程需要等待一个数据才能继续计算,主线程将该数据准备完成后应通知副线程继续运行。以下代码中原书分别将其称为 react 和 detect 线程。)一种方法是使用 std::condition_variable:创建变量 cv,副线程调用 wait 阻塞等待信号;主线程准备完成后调用 notify_one 或 notify_all 发出信号,简单代码如下:..

2022-04-02 20:44:56 413

原创 《Effective Modern C++》学习笔记 - Item 38: 注意future析构函数的不同行为

std::thread 和非延迟的 std::future 内部都对应着一个实际的线程,可以认为这些对象是我们对系统线程的 handle。从这个角度来看,std::thread 和 future 在析构函数中有不同的行为是比较奇怪的:如 Item 37 所述,销毁一个 joinable 的 std::thread 会导致程序终止;然而销毁 future 有时会表现地如隐式执行了 join,有时如隐式执行了 detach,有时二者皆非,但无论如何都不会导致程序终止。本节中,我们就对 future 的..

2022-04-01 00:04:32 1231

原创 《Effective Modern C++》学习笔记 - Item 37: 保证std::thread在所有运行路径上最终unjoinable

每个 std::thread 对象随时处于两种状态之一:joinable 或 unjoinable。处于 joinable 状态意味着 std::thread 对象必须对其内部的线程资源负责,该线程的状态可以是等待执行、正在执行或已经完成执行。而 unjoinbale 状态正相反,具体包括几种情况:默认构造的 std::thread。它们没有要执行的函数,因此也不会真正持有一个线程。已经被用于移动构造其它对象的 std::thread。移动操作将其内部持有线程的控制权交给了其它对象,因此它不再负责管.

2022-03-29 23:14:02 1024

原创 《Effective Modern C++》学习笔记 - Item 36: 如果异步性是必要的,指明std::launch::async

如上节所述,使用 std::async 相比手动创建线程有若干优点。但是,调用 std::async 不保证传入的函数(或 callable object)一定是在其它线程异步运行的。std::async 实际是遵循 运行策略(launch policy) 执行的,标准库在 std::launch 枚举类中声明了两种策略(设待执行的函数名为 f ):std::launch::async 运行策略表示 f 必须 被异步地(即在另一个线程上)执行。std::launch::deferred 运行..

2022-03-26 23:16:06 1495

原创 《Effective Modern C++》学习笔记 - Item 35: 倾向于基于任务而非基于线程的编程方式

本节开始我们进入全书第7章:并发 API本节太长不看版:使用基于线程的编程方式,你需要自己管理线程的生命周期,考虑线程性能相关的多种问题,而且无法直接获取返回值;而使用基于任务的方式,这些问题全部交由标准库实现解决,而且可以通过 get() 获取返回值。C++11 中,想要异步运行一个函数 doAsyncWork() 有两种基本选择:基于线程(thread-based)的方法:创建一个 std::thread,并让它运行 doAsyncWork。#include <thread&g..

2022-03-25 22:13:55 806

原创 《Effective Modern C++》学习笔记 - Item 34: 倾向于使用lambda函数而非std::bind

太长不看版:std::bind 是2005年TR1提案引入的特性,相比C++98的 std::bind1st 和 std::bind2nd 是一个大进步;但到了C++11时代,lambda 函数几乎可以代替它,但仍剩余几种特定情况适合使用 std::bind。C++14消灭了这些情况,现在 lambda 函数已经完全是 std::bind 的上位替代。本节通过几个例子来展示 lambda 相比std::bind的若干优势。我们假设你已经熟悉 std::bind 的基本使用。lambda 的第..

2022-03-24 19:32:18 968

原创 《Effective Modern C++》学习笔记 - Item 33: 对auto&&参数使用decltype以转发它们

C++14 为我们带来了泛型 lambda(generic lambda),可以在参数声明中使用 auto。这个特性的实现原理也不难想到:将 lambda 生成类的 operator() 变为一个模板函数即可。例如,下面的 lambda 函数在编译中产生的类可能形如:auto f = [](auto x){ return func(normalize(x)); };↓class SomeCompilerGeneratedClassName {public: template<typena.

2022-03-15 20:50:51 1203

原创 《Effective Modern C++》学习笔记 - Item 32: 使用初始化捕获将对象移动至lambda函数中

C++11 中 lambda 函数捕获参数的语义只有两种:按值捕获 [=] 和按引用捕获 [&],而且只能声明变量名,不支持表达式。这导致了一个问题:无法使用移动构造的参数。这对于拷贝成本高而移动成本低的对象(如STL中的大部分容器)以及只能移动构造的对象(如 std::unique_ptr 和 std::future)是很不友好的。C++14 对此做了改进,引入了一种新的捕获机制:初始化捕获(init capture),或者叫广义 lambda 捕获(generalized lambda..

2022-03-15 19:55:56 1011

原创 《Effective Modern C++》学习笔记 - Item 30: 了解完美转发失效的场景

完美转发(perfect forwarding),是指一个函数将其参数完整传递给另一个函数,使得第二个函数接受的对象与第一个函数完全相同,包括其类型、是左值还是右值、是否是 const 或 volatile 的属性。因此我们这里讨论的只有万能引用参数,只有它们能携带这些信息。以下面这个函数为例:template<typename T>void fwd(T&& param) // accept any argument{ f(std::forward<T&g.

2022-03-12 23:00:22 1034

原创 《Effective Modern C++》学习笔记 - Item 29: 移动操作的“坑点”:它们可能不存在,开销不小或不会被调用

移动语义无疑是C++11的一个重要特性,然而人们容易对其期待过高。本节就来介绍一些移动操作并不能带来性能提升的情景,目的是使我们对移动操作的作用范围有更加理性的认识。以下所述的移动操作均为移动构造函数和移动赋值运算符两项的集合。首先,很多类型不支持移动语义。虽然C++11的STL实现已经针对移动操作做了改进,但你正在使用的其它符合C++98标准的库可能并非如此。的确,编译器会自动为类生成移动操作,但根据 Item 17,只有当该类没有声明拷贝操作、(另一种)移动操作和析构函数时才会如此。对于没有显..

2022-03-05 18:15:06 625

原创 《Effective Modern C++》学习笔记 - Item 28: 理解引用折叠(reference collapsing)

本节中,我们来讨论“万能引用”这种抽象的本质,以及 std::forward 的实现机理。Item 23和24中说明了当使用万能引用参数 T&& 时,入参的类型信息会被记录在 T 中。规则实际上很简单:当入参为左值时,T(注意,不是 T&&)被推导为左值引用;当入参为右值时,T 被推导为非引用(注意这里的不对称性)。以一个例子来说明:template<typename T>void func(T&& param);Widget..

2022-03-01 15:33:52 859 2

原创 《Effective Modern C++》学习笔记 - Item 27: 了解对万能引用参数进行重载的替代方案

本节是 Item 26 的延续。上一节中我们已经了解了为什么对万能引用参数进行重载是种糟糕的做法,这一节就来讨论其替代做法。方法一:放弃使用重载最简单的方法。例如,上一节中的 logAndAdd 函数可以拆为两个 logAndAddName 和 logAndAddIdx。但这种方法对构造函数的情景不适用,因为构造函数的名称是固定的。再说了,重载多好用,谁又想放弃呢?方法二:按 const T& 传递也就是回到上一节的最初版本,放弃使用万能引用。如之前讨论,这样的代码效率不是..

2022-02-21 23:11:13 615

原创 《Effective Modern C++》学习笔记 - Item 26: 避免对万能引用参数进行重载

假设有下面这样一个函数,它将一个字符串参数 name 加入到全局数据集合 names 中,同时记录当前时间:std::multiset<std::string> names; // global data structurevoid logAndAdd(const std::string& name){ auto now = // get current time std::chrono::system_clock::now(); log(now, .

2022-02-19 16:52:18 843

原创 《Effective Modern C++》学习笔记 - Item 25: 对右值引用参数使用std::move,对万能引用参数使用std::forward

在函数中,对右值引用的参数使用 std::move,对万能引用的参数使用 std::forward,不能用反:对右值引用使用 std::forward<T>() 需要额外写一遍类型 T,代码冗余容易出错;对万能引用使用 std::move 更糟糕,因为万能引用参数可以绑定到左值引用,使用 std::move 可能会错误地破坏传入的左值参数(准确来说,是错误地将其强制转型为右值,导致后续使用时可能被破坏)。在一个函数中如果要多次使用一个右值/万能引用对象,仅在最后一次对其用 st..

2022-02-19 12:20:11 602

原创 《Effective Modern C++》学习笔记 - Item 24: 区分万能引用和右值引用

T&& 有两种含义:右值引用,只能绑定到右值上。万能引用(作者称为 “universal references” ),可以绑定到任何类型的变量上,包括左值或右值,const 或 non-const,volatile 或 non-volatile,以及以上的任何组合。万能引用出现在两个情景中:模板函数的参数, 形式为:template<typename T>void f(T&& param); // param is a universa..

2022-02-14 22:55:08 559

原创 《Effective Modern C++》学习笔记 - Item 23: 理解 std::move 和 std::forward

std::move 不会移动任何东西,std::forward 不会传递任何东西。二者在运行时什么都不会做。std::move 和 std::forward 只是执行类型转换(cast)的函数(模板)。std::move 无条件地将参数转换为右值,而 std::forward 只有当满足某个条件时才做如此转换。就这样。看看 std::move 的实现:// GCC版本,MSVC与之区别仅在于将 remove_reference<_Tp>::type换成了remove_reference.

2022-01-28 12:03:58 1236

原创 《Effective Modern C++》学习笔记 - Chapter 5. 右值引用,移动语义和完美转发

第五章第一次学习时,移动语义和完美转发的意思看起来很直白:移动语义使编译器能把昂贵的拷贝操作换为移动操作。类似于拷贝构造/赋值函数,你可以通过移动构造/赋值函数来控制移动的语义。移动语义还允许你创建仅移动(不能复制)的类型,如 std::unique_ptr,std::future 和 std::thread。完美转发允许函数模板接受任意(左值/右值)参数,并将它们原样传递给其它的函数。右值引用是使以上二者可能实现的低层语言机制然而随着对这些特性的掌握变深,你会发现最初的印象只是冰

2022-01-24 17:38:33 502

原创 《Effective Modern C++》学习笔记 - Item 22: 使用 Pimpl 手法时,在实现文件中定义特殊成员函数

Pimpl (pointer-to-implementation) 是一种常用的类设计手法,可以实现:(1)只暴露函数调用接口,隐藏实现细节;(2)避免修改实现时导致调用者的代码必须重新编译,提高构建速度。实现 Pimpl 的方法正如其名:头文件(.h)中,去除类中所有私有成员;声明(而不定义)一个 impl 类型,为类添加一个 private 的 impl 指针。实现文件中,定义 impl 类型,包含所有私有成员,其它函数实现通过 impl 指针访问它们;构造和析构函数实现中,new 和 delete .

2022-01-17 11:21:59 732

原创 《Effective Modern C++》学习笔记 - Item 21: 倾向于使用 std::make_unique 和 std::make_shared 而非直接使用 new

注:本节所述内容对于C++11、14和C++17标准来说有一些不同。原书基于前者讲解,笔者会标注出C++17的变化。std::make_unique 和 std::make_shared 函数正如其名称所示,用于创造一个 std::unique_ptr 或 std::shared_ptr。它们接收任意多个参数,第一个参数作为管理的对象类型,并将剩余所有参数完美转发给对象类型的构造函数。与 std::make_shared 类似的还有一个 std::allocate_shared,区别在于其第一个参..

2022-01-16 22:15:20 410

空空如也

空空如也

TA创建的收藏夹 TA关注的收藏夹

TA关注的人

提示
确定要删除当前文章?
取消 删除