文件断点续传是一种机制,允许在网络传输中的文件传输过程中出现断开连接或传输中断的情况下,能够恢复传输并继续传输未完成的部分。其原理如下:
多态分为静态多态和动态多态。静态多态是指在编译期实现的多态,具体可以分为函数重载和模版。函数重载是通过name mangling
实现。动态多态是在运行期实现的多态,主要是通过重写虚函数实现,需要使用虚函数表和虚函数指针。
每个包含虚函数的类都有一个虚函数表(vtable)。虚函数表是一个指向虚函数指针的数组,这些指针指向类的虚函数实现。每个对象包含一个指向虚函数表的指针,称为虚指针(vptr)。当对象被创建时,构造函数会初始化这个虚指针,指向对象所属类的虚函数表。当通过基类指针或引用调用虚函数时,实际上是通过虚指针找到虚函数表,然后在表中找到对应的函数指针并调用它。这个过程确保调用的是实际对象的函数实现,而不是基类的实现。
虚函数表(vtable)存储在静态内存区域中,每个类有一个虚函数表。虚指针(vptr)是每个对象的隐式成员,存储在对象的内存布局中,指向该对象所属类的虚函数表。
头部压缩:
HTTP/2 会压缩头(Header)如果你同时发出多个请求,他们的头是⼀样的或是相似的,那么,协议会帮你消除重复的部分。
这就是所谓的 HPACK 算法:在客户端和服务器同时维护一张头信息表,所有字段都会存如这个表,生成⼀个索引号,以后就不发送同样字段了,只发送索引号,这样就提高速度了。
二进制格式:
HTTP/2 不再像 HTTP/1.1 里的纯文本形式的报文,而是全面采用了二进制格式,头信息和数据体都是二进制,并且统称为帧(frame):头信息帧和数据帧。增加了数据传输的效率。
数据流:
HTTP/2 的数据包不是按顺序发送的,同⼀个连接里面连续的数据包,可能属于不同的回应。因此,必须要对数据包做标记,指出它属于哪个回应。
每个请求或回应的所有数据包,称为⼀个数据流( Stream )。每个数据流都标记着⼀个独一无二的编号,其中规定客户端发出的数据流编号为奇数, 服务器发出的数据流编号为偶数。
客户端还可以指定数据流的优先级。优先级⾼的请求,服务器就先响应该请求。
多路复用:
HTTP/2 是可以在⼀个连接中并发多个请求或回应,而不用按照顺序⼀⼀对应。
移除了 HTTP/1.1 中的串行请求,不需要排队等待,也就不会再出现「队头阻塞」问题,降低了延迟,⼤幅度提高了连接的利用率。
举例来说,在⼀个 TCP 连接里,服务器收到了客户端 A 和 B 的两个请求,如果发现 A 处理过程非常耗时,于是就回应 A 请求已经处理好的部分,接着回应 B 请求,完成后,再回应 A 请求剩下的部分。
服务器推送:
HTTP/2 还在⼀定程度上改善了传统的「请求 - 应答」工作模式,服务不再是被动地响应,也可以主动向客户端发送消息。
举例来说,在浏览器刚请求 HTML 的时候,就提前把可能会用到的 JS、CSS ⽂件等静态资源主动发给客户端,减少延时的等待,也就是服务器推送(Server Push,也叫 Cache Push)。
模块是C++20引入的一种新特性,用于替代传统的头文件机制,旨在改善代码的模块化和编译时间。
// my_module.cpp export module my_module; // 定义并导出模块 export void greet() { std::cout << "Hello from module!\n"; } // main.cpp import my_module; // 导入模块 int main() { greet(); }
协程是一种用于简化异步编程的新特性,使得可以通过更直观的方式来编写异步代码。
#include #include struct Generator { struct promise_type; using handle_type = std::coroutine_handle; struct promise_type { int value; auto get_return_object() { return Generator{handle_type::from_promise(*this)}; } auto initial_suspend() { return std::suspend_always{}; } auto final_suspend() noexcept { return std::suspend_always{}; } void return_void() {} void unhandled_exception() { std::exit(1); } auto yield_value(int val) { value = val; return std::suspend_always{}; } }; handle_type h; Generator(handle_type h) : h(h) {} ~Generator() { h.destroy(); } bool next() { return h.resume(), !h.done(); } int value() const { return h.promise().value; } }; Generator sequence() { for (int i = 0; i < 3; ++i) co_yield i; } int main() { auto gen = sequence(); while (gen.next()) { std::cout << gen.value() << "\n"; } }
范围库提供了一组更强大和灵活的方式来操作集合,使得代码更简洁和易读。
#include #include #include #include int main() { std::vector v = { 5, 2, 1, 3, 0, 4, 6 }; // 过滤和变换范围 auto result = v | std::views::filter([](int n) { return n % 2 == 0; }) | std::views::transform([](int n) { return n * n; }); for (int n : result) { std::cout << n << " "; } std::cout << "\n"; std::ranges::sort(v); for (int x : v) { std::cout << x << " "; } }
概念用于为模板定义约束条件,提高模板的可读性和错误信息的清晰度。
c#include #include // 定义一个概念,约束类型必须支持加法操作 template concept Addable = requires(T a, T b) { { a + b } -> std::convertible_to; }; template T add(T a, T b) { return a + b; } int main() { std::cout << add(1, 2) << std::endl; // 合法 // std::cout << add("Hello, ", "world!"); // 非法,不满足Addable概念 }
进程 | 线程 | 协程 |
---|---|---|
线程1 | 协程1 | 函数调用1 |
协程2 | 函数调用2 | |
线程2 | 协程3 | 函数调用3 |
协程4 | 函数调用4 | |
线程3 | 协程5 | 函数调用5 |
协程6 | 函数调用6 | |
资源 | 资源 | 资源 |
std::unique_ptr
std::unique_ptr
表示唯一所有权的智能指针,即一个对象只能有一个std::unique_ptr
实例管理。std::unique_ptr
不可复制,但可以移动(使用std::move
)。std::unique_ptr
超出作用域时,它所管理的对象会自动被删除。std::unique_ptr
的开销较小。std::shared_ptr
std::shared_ptr
表示共享所有权的智能指针,即多个std::shared_ptr
实例可以管理同一个对象。std::shared_ptr
使用引用计数来跟踪对象的使用情况,当引用计数为零时,自动删除对象。std::shared_ptr
超出作用域时,它所管理的对象会被删除。std::weak_ptr
std::weak_ptr
是与std::shared_ptr
配合使用的智能指针,用于解决循环引用问题。std::weak_ptr
不会影响对象的引用计数,因此不会阻止对象的删除。std::weak_ptr
可以观察std::shared_ptr
管理的对象,但不能直接访问对象,必须通过lock
方法获取std::shared_ptr
。LeetCode 131原题,同时最好也把132,1278,1745几个加强版也做了。
class Solution { public: std::vector> partition(std::string s) { std::ios::sync_with_stdio(false); std::cin.tie(nullptr); std::vector> ans; std::vector path; int n = s.length(); std::function dfs = [&] (int idx) { if (idx == n) { ans.push_back(path); return; } std::string tmp; for (int i = idx; i < n; ++i) { tmp += s[i]; bool f = true; // 可以提前使用dp预处理,或者记忆化结果 for (int i = 0; i * 2 + 1 < tmp.length(); ++i) { if (tmp[i] != tmp[tmp.size()-1-i]) { f = false; break; } } if (f) { path.push_back(tmp); dfs(i + 1); path.pop_back(); } } }; dfs(0); return ans; } };
最后给大家推荐一个LinuxC/C++高级架构系统教程的学习资源与课程,可以帮助你有方向、更细致地学习C/C++后端开发,具体内容请见 https://xxetb.xetslk.com/s/1o04uB