<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Posts on liubang's blog</title><link>https://blog.liubang.cc/posts/</link><description>Recent content in Posts on liubang's blog</description><generator>Hugo</generator><language>en</language><copyright>Copyright © 2019-2026 LiuBang. All Rights Reserved.</copyright><lastBuildDate>Sun, 12 Apr 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://blog.liubang.cc/posts/index.xml" rel="self" type="application/rss+xml"/><item><title>一文讲透 AI 九大核心概念</title><link>https://blog.liubang.cc/posts/llm/2026-04-12-ai-ai-concepts-explained/</link><pubDate>Sun, 12 Apr 2026 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/llm/2026-04-12-ai-ai-concepts-explained/</guid><description><![CDATA[<blockquote>
<p>AI 圈每天都在冒新词。但你真的能准确说出每一个概念的确切含义吗？本文从最底层的工程视角出发，逐层拆解，帮你建立完整的 AI 技术认知体系。</p>
</blockquote>
<hr>

<h2 id="llm--一切的基础" data-numberify>LLM —— 一切的基础<a class="anchor ms-1" href="#llm--一切的基础"></a></h2>
<p><strong>LLM</strong>，全称 <strong>Large Language Model</strong>，中文译作<strong>大语言模型</strong>，简称<strong>大模型</strong>。</p>
<p>当前几乎所有主流大模型，底层都基于同一套架构——<strong>Transformer</strong>。这个架构最早由 Google 团队在 2017 年提出，对应的论文标题叫做《Attention Is All You Need》（注意力机制就是全部所需）。</p>
<p>虽然 Google 发明了这把火，但真正点燃全世界的是 OpenAI。</p>
<ul>
<li><strong>2022 年底</strong>，ChatGPT（GPT-3.5）横空出世，成为第一个真正达到&quot;可用级别&quot;的大模型；</li>
<li><strong>2023 年 3 月</strong>，GPT-4 发布，把 AI 的能力天花板拉到了新高度。</li>
</ul>
<p>GPT 系列是这轮 AI 浪潮的绝对引路人。时至今日，GPT 系列依然非常强大，如 GPT-4.5 仍是行业标杆之一。但如今 AI 赛道早已不是 OpenAI 一家独大，Claude、Gemini 等后起之秀都在各自擅长的领域与之同台竞技。</p>

<h3 id="大模型是如何工作的" data-numberify>大模型是如何工作的？<a class="anchor ms-1" href="#大模型是如何工作的"></a></h3>
<p>大模型本质上是一个<strong>文字接龙游戏</strong>。</p>
<p>举个例子，你向大模型提问：「马克的视频怎么样」</p>
<ol>
<li>模型接收这句话，经过内部运算，预测下一个概率最高的词：<strong>「特」</strong></li>
<li>模型把「特」追加到输入后面，再预测下一个词：<strong>「别」</strong></li>
<li>如此循环，直到预测出特殊的<strong>结束标记</strong></li>
</ol>
<p>最终输出：「特别棒」</p>
<p>这就是大模型最底层的生成原理——<strong>一个词一个词地输出答案，因为它就是这么运作的</strong>。</p>
<p><picture><img class="img-fluid " alt="LLM 文字接龙流程图" src="https://blog.liubang.cc/images/2026-04-12/llm-next-token.svg?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" />
</picture>

</p>
<hr>

<h2 id="token--大模型的最小单位" data-numberify>Token —— 大模型的"最小单位"<a class="anchor ms-1" href="#token--大模型的最小单位"></a></h2>
<p>大模型本质上是一个庞大的数学系统，接收的是数字，输出的也是数字，<strong>根本不认识人类书写的文字</strong>。</p>
<p>因此，在人类和大模型之间必须有一个中间人来做翻译，这个中间人就叫做 <strong>Tokenizer</strong>。它负责两件事：</p>
<ul>
<li><strong>编码（Encode）</strong>：把文字变成数字</li>
<li><strong>解码（Decode）</strong>：把数字还原成文字</li>
</ul>

<h3 id="token-化的过程" data-numberify>Token 化的过程<a class="anchor ms-1" href="#token-化的过程"></a></h3>
<p>编码分两步：</p>]]></description></item><item><title>BloomFilter中的数学推导</title><link>https://blog.liubang.cc/posts/storage/2025-01-01-bloomfilter%E4%B8%AD%E7%9A%84%E6%95%B0%E5%AD%A6%E6%8E%A8%E5%AF%BC/</link><pubDate>Wed, 01 Jan 2025 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/storage/2025-01-01-bloomfilter%E4%B8%AD%E7%9A%84%E6%95%B0%E5%AD%A6%E6%8E%A8%E5%AF%BC/</guid><description><![CDATA[<h2 id="false-positive-rate" data-numberify>False Positive Rate<a class="anchor ms-1" href="#false-positive-rate"></a></h2>
<p>$m$: 表示BloomFilter bit array的长度;<br>
$k$: 表示hash函数个数;<br>
$n$: 表示插入元素的个数;</p>
<p>假设hash函数以等概率选择bit array的下标，那么经过$k$个hash函数之后，某个bit位未被设置为1的概率为:</p>
<p>$$
(1 - \frac{1}{m})^k
$$</p>
<p>在插入$n$个元素之后，某个bit位仍然没有被设置为1的概率为:</p>
<p>$$
(1 - \frac{1}{m})^{kn}
$$</p>
<p>因此在插入$n$个元素之后，某个bit位被设置为1的概率为:</p>
<p>$$
p = 1 - (1 - \frac{1}{m})^{kn}
$$</p>
<p>对于一个不存在于集合中的元素，如果要出现误判，那么意味着经过$k$个hash函数之后，生成的下标所在的bit位
都是1，其概率为:</p>
<p>$$
\epsilon = p^k = (1 - (1 - \frac{1}{m})^{kn})^k
$$</p>
<p>接着来用欧拉公式来对上面的式子进行简化，已知欧拉公式可表示为:</p>
<p>$$
\lim_{m \to \infty}(1 + \frac{z}{m})^m = e^z
$$</p>
<p>令$z = -1$</p>
<p>$$
\lim_{m \to \infty}(1 - \frac{1}{m})^m = e^{-1}
$$</p>]]></description></item><item><title>使用LLVM的libFuzzer进行fuzzy test</title><link>https://blog.liubang.cc/posts/cpp/2023-05-23-%E4%BD%BF%E7%94%A8llvm%E7%9A%84libfuzzer%E8%BF%9B%E8%A1%8Cfuzzy-test/</link><pubDate>Tue, 23 May 2023 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2023-05-23-%E4%BD%BF%E7%94%A8llvm%E7%9A%84libfuzzer%E8%BF%9B%E8%A1%8Cfuzzy-test/</guid><description><![CDATA[<h2 id="libfuzzer-简介" data-numberify>libFuzzer 简介<a class="anchor ms-1" href="#libfuzzer-简介"></a></h2>
<p>LLVM libFuzzer 是 LLVM 生态系统中的一个fuzzy test工具，用于自动化地发现软件程序中的漏洞和错误。它通过生成大量的随机输入数据并观察程序的行为来进行fuzzy test。
libFuzzer 是一个基于内存的fuzzy test引擎，使用 LLVM 的插桩技术和代码优化功能来提高测试效率和覆盖率。</p>
<p>以下是 libFuzzer 的一些功能特点：</p>
<ol>
<li>自动化fuzzy test：libFuzzer 提供了一种自动化的fuzzy test方法，可以生成大量的随机输入数据，并在每个输入上运行目标函数进行测试。它通过观察程序的崩溃、断言失败、未定义行为等反馈来发现潜在的问题。</li>
<li>内存安全性：libFuzzer 通过使用 AddressSanitizer (ASan) 和 UndefinedBehaviorSanitizer (UBSan) 等工具来确保fuzzy test过程中的内存安全性。这有助于检测和报告内存错误、缓冲区溢出、使用已释放内存等问题。</li>
<li>代码覆盖率分析：libFuzzer 使用 LLVM 提供的代码覆盖率分析技术，帮助确定已经执行过的代码路径和未执行的代码区域。这有助于评估测试的质量和覆盖范围，并帮助发现潜在的漏洞。</li>
<li>快速收敛：libFuzzer 使用一种称为 &ldquo;回退&rdquo;（Backoff）的策略，以更快地收敛到程序中的漏洞。它会根据测试结果调整输入数据的变异程度，使得能够更快地发现问题并生成更有潜力的测试用例。</li>
<li>灵活性和可定制性：libFuzzer 提供了多种选项和配置参数，使用户能够根据自己的需求进行定制。例如，可以设置最大测试时间、内存消耗限制、覆盖率报告等。</li>
<li>多线程支持：libFuzzer 支持多线程执行，可以利用多核处理器并行进行fuzzy test，加快测试速度。</li>
</ol>

<h2 id="示例" data-numberify>示例<a class="anchor ms-1" href="#示例"></a></h2>
<p>下面是一个使用 libFuzzer 的简单示例</p>
<p>首先我们有一个 test_fuzzy.cpp:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;cstddef&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;cstdint&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">DoSomethingWithData</span>(<span style="color:#c678dd">const</span> <span style="color:#e5c07b">uint8_t</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">data</span>, <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">size</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>  <span style="color:#e5c07b">int</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">p</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">nullptr</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>  <span style="color:#c678dd">if</span> (<span style="color:#e06c75">size</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#d19a66">10</span>) <span style="color:#c678dd">return</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>  <span style="color:#c678dd">if</span> (<span style="color:#e06c75">data</span>[<span style="color:#d19a66">0</span>] <span style="color:#56b6c2">==</span> <span style="color:#98c379">&#39;h&#39;</span> <span style="color:#56b6c2">&amp;&amp;</span> <span style="color:#e06c75">data</span>[<span style="color:#d19a66">1</span>] <span style="color:#56b6c2">==</span> <span style="color:#98c379">&#39;e&#39;</span> <span style="color:#56b6c2">&amp;&amp;</span> <span style="color:#e06c75">data</span>[<span style="color:#d19a66">2</span>] <span style="color:#56b6c2">==</span> <span style="color:#98c379">&#39;l&#39;</span> <span style="color:#56b6c2">&amp;&amp;</span> <span style="color:#e06c75">data</span>[<span style="color:#d19a66">3</span>] <span style="color:#56b6c2">==</span> <span style="color:#98c379">&#39;l&#39;</span> <span style="color:#56b6c2">&amp;&amp;</span> <span style="color:#e06c75">data</span>[<span style="color:#d19a66">4</span>] <span style="color:#56b6c2">==</span> <span style="color:#98c379">&#39;0&#39;</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#56b6c2">*</span><span style="color:#e06c75">p</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">42</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>  }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>  <span style="color:#c678dd">return</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#c678dd">extern</span> <span style="color:#98c379">&#34;C&#34;</span> <span style="color:#e5c07b">int</span> <span style="color:#e06c75">LLVMFuzzerTestOneInput</span>(<span style="color:#c678dd">const</span> <span style="color:#e5c07b">uint8_t</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">data</span>, <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">size</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>  <span style="color:#e06c75">DoSomethingWithData</span>(<span style="color:#e06c75">data</span>, <span style="color:#e06c75">size</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>  <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>}
</span></span></code></pre></div><p>使用 clang++进行编译：</p>]]></description></item><item><title>Rust和C++: 泛型和特例化</title><link>https://blog.liubang.cc/posts/rust/2022-11-13-rust%E5%92%8Cc++%E5%AF%B9%E6%AF%94%E4%B9%8B%E6%B3%9B%E5%9E%8B%E5%92%8C%E7%89%B9%E4%BE%8B%E5%8C%96/</link><pubDate>Sat, 12 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/rust/2022-11-13-rust%E5%92%8Cc++%E5%AF%B9%E6%AF%94%E4%B9%8B%E6%B3%9B%E5%9E%8B%E5%92%8C%E7%89%B9%E4%BE%8B%E5%8C%96/</guid><description><![CDATA[<blockquote>
<p>Ref: <a href="https://www.tangramvision.com/blog/c-rust-generics-and-specialization" target="_blank" rel="noopener noreferrer">https://www.tangramvision.com/blog/c-rust-generics-and-specialization<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
</blockquote>

<h2 id="泛型入门输入的类型" data-numberify>泛型入门：输入的类型<a class="anchor ms-1" href="#泛型入门输入的类型"></a></h2>
<p>C++和 Rust 中的泛型都是一种将其他类型作为其定义的一部分的类型。泛型是通过在类型定义中指定占位符的一种方式，然后可以
使用更具体的类型来替换，例如在 C++中可以这定义一个泛型类型：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e5c07b">MyArray</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e06c75">T</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">raw_array</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">size</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>};
</span></span></code></pre></div><p>对于这个泛型结构而言，<code>MyArray&lt;int&gt;</code>和<code>MyArray&lt;std::string&gt;</code>是不同的类型。我们可以通过指定具体的<code>T</code>类型，来复用<code>MyArray</code>这个泛型结构体。这里的<code>MyArray&lt;T&gt;</code>就像一个“模板”一样。
泛型不仅仅局限于结构体，我们同样也能写出泛型函数：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span><span style="color:#e06c75">T</span> <span style="color:#e06c75">timestwo</span>(<span style="color:#e06c75">T</span> <span style="color:#e06c75">number</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#e06c75">number</span> <span style="color:#56b6c2">+</span> <span style="color:#e06c75">number</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>}
</span></span></code></pre></div><p>上面我们定义了一个非常简单的函数，用来将数值加倍。同理，用具体类型实例化的<code>timestwo&lt;int&gt;</code>和<code>timestwo&lt;double&gt;</code>也不是同一个函数。</p>
<p>而要在 Rust 中实现上面的函数，可能稍微复杂一点：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a></span><span><span style="color:#c678dd">use</span> <span style="color:#e06c75">std</span>::<span style="color:#e06c75">ops</span>::<span style="color:#e06c75">Add</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-2">2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-3">3</a></span><span><span style="color:#c678dd">fn</span> <span style="color:#61afef;font-weight:bold">timestwo</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span>(<span style="color:#e06c75">number</span>: <span style="color:#e5c07b">T</span>) -&gt; <span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span> <span style="color:#c678dd">as</span> <span style="color:#e06c75">Add</span><span style="color:#56b6c2">&gt;</span>::<span style="color:#e06c75">Output</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-4">4</a></span><span><span style="color:#c678dd">where</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-5">5</a></span><span>    <span style="color:#e06c75">T</span>: <span style="color:#e5c07b">Add</span> <span style="color:#56b6c2">+</span> <span style="color:#e5c07b">Copy</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-6">6</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-7">7</a></span><span>    <span style="color:#e06c75">number</span> <span style="color:#56b6c2">+</span> <span style="color:#e06c75">number</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-8">8</a></span><span>}
</span></span></code></pre></div><p>很显然，上面 Rust 版本和 C++版本的实现相比看上去多了很多额外的语法。其中主要的区别是我们调用了特征边界检查，也就是<code>T: Add + Copy</code>，
或者用更通俗的话来说，<code>T</code>类型必须实现<code>Add</code>和<code>Copy</code> 特征(trait)。</p>]]></description></item><item><title>Rust和C++: 可变性、移动和所有权</title><link>https://blog.liubang.cc/posts/rust/2022-11-01-rust%E5%92%8Cc++%E5%AF%B9%E6%AF%94%E4%B9%8B%E5%8F%AF%E5%8F%98%E6%80%A7%E7%A7%BB%E5%8A%A8%E5%92%8C%E6%89%80%E6%9C%89%E6%9D%83/</link><pubDate>Tue, 01 Nov 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/rust/2022-11-01-rust%E5%92%8Cc++%E5%AF%B9%E6%AF%94%E4%B9%8B%E5%8F%AF%E5%8F%98%E6%80%A7%E7%A7%BB%E5%8A%A8%E5%92%8C%E6%89%80%E6%9C%89%E6%9D%83/</guid><description><![CDATA[<blockquote>
<p>Ref: <a href="https://www.tangramvision.com/blog/c-rust-interior-mutability-moving-and-ownership" target="_blank" rel="noopener noreferrer">https://www.tangramvision.com/blog/c-rust-interior-mutability-moving-and-ownership<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
</blockquote>

<h2 id="c和-rust-中的不变性constness" data-numberify>C++和 Rust 中的不变性(constness)<a class="anchor ms-1" href="#c和-rust-中的不变性constness"></a></h2>

<h3 id="值" data-numberify>值<a class="anchor ms-1" href="#值"></a></h3>
<p>Rust 和 C++有两个非常相似的概念，即 Rust 中的 mutability/immutability 和 C++中的 constness/non-constness.
在 Rust 中，一个给定的值要么是可变的(mutable)，要么是不可变的(immutable)，正如这些限定符名称所代表的含义，可变的值可以被修改，不可变的值不能被修改。
然而与 C++不同的是，Rust 中不可变的值可以被移动(move)，就像下面的代码实例那样：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-rust" data-lang="rust"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">fn</span> <span style="color:#61afef;font-weight:bold">foo</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#c678dd">let</span> <span style="color:#e06c75">x</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">1</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#56b6c2;font-weight:bold">println!</span>(<span style="color:#98c379">&#34;</span><span style="color:#98c379">{}</span><span style="color:#98c379">&#34;</span>, <span style="color:#e06c75">x</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#c678dd">let</span> <span style="color:#c678dd">mut</span> <span style="color:#e06c75">x</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">x</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>    <span style="color:#e06c75">x</span> <span style="color:#56b6c2">*=</span> <span style="color:#d19a66">10</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6">6</a></span><span>    <span style="color:#56b6c2;font-weight:bold">println!</span>(<span style="color:#98c379">&#34;</span><span style="color:#98c379">{}</span><span style="color:#98c379">&#34;</span>, <span style="color:#e06c75">x</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7">7</a></span><span>}
</span></span></code></pre></div><p>在 C++中，给定的值要么是常量(const)，要么是非常量(non-const)。但是 C++中的常量值不能被移动(move)。在 C++中，对一个 const 限定符修饰的值
进行<code>std::move</code>操作，实际上会触发拷贝构造，这一点在&quot;Effective Modern C++&ldquo;这本书中作者也有提到：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">Annotation</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>    <span style="color:#c678dd">explicit</span> <span style="color:#e06c75">Annotation</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span> <span style="color:#e06c75">text</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>     <span style="color:#56b6c2">:</span> <span style="color:#e06c75">value</span>(<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">move</span>(<span style="color:#e06c75">text</span>)) <span style="color:#7f848e">//here we want to call string(string&amp;&amp;),
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>                              <span style="color:#7f848e">//but because text is const,
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>                              <span style="color:#7f848e">//the return type of std::move(text) is const std::string&amp;&amp;
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span>                              <span style="color:#7f848e">//so we actually called string(const string&amp;)
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>                              <span style="color:#7f848e">//it is a bug which is very hard to find out
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>    {}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span><span style="color:#c678dd">private</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span> <span style="color:#e06c75">value</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span>};
</span></span></code></pre></div><p>我们也可以自己写一段程序来验证一下：</p>]]></description></item><item><title>为什么c++中有了函数指针却还需要std::function</title><link>https://blog.liubang.cc/posts/cpp/2022-09-28-%E4%B8%BA%E4%BB%80%E4%B9%88c++%E4%B8%AD%E6%9C%89%E4%BA%86%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88%E5%8D%B4%E8%BF%98%E9%9C%80%E8%A6%81stdfunction/</link><pubDate>Wed, 28 Sep 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-09-28-%E4%B8%BA%E4%BB%80%E4%B9%88c++%E4%B8%AD%E6%9C%89%E4%BA%86%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88%E5%8D%B4%E8%BF%98%E9%9C%80%E8%A6%81stdfunction/</guid><description><![CDATA[<p>在C/C++中，我们经常会像下面的代码那样使用一个指向函数的指针，我们称之为函数指针：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// demo.c
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">func</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">a</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#e06c75">a</span> <span style="color:#56b6c2">+</span> <span style="color:#d19a66">1</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">argv</span>[]) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#e5c07b">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">f</span>)(<span style="color:#e5c07b">int</span>) <span style="color:#56b6c2">=</span> <span style="color:#e06c75">func</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#e06c75">printf</span>(<span style="color:#98c379">&#34;%p</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#e06c75">f</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>}
</span></span></code></pre></div><p>上面的例子中，我们定义了一个函数<code>func</code>，然后通过函数指针<code>f</code>指向<code>func</code>，接着使用<code>print</code>函数打印指针变量<code>f</code>指向
的地址。代码平淡无奇，接着我们编译代码，然后使用<code>objdump -D demo</code>来查看生成的二进制结构如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#d19a66">0000000100003f</span><span style="color:#d19a66">34</span> <span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">_func</span><span style="color:#56b6c2">&gt;:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span><span style="color:#d19a66">100003f</span><span style="color:#d19a66">34</span><span style="color:#56b6c2">:</span> <span style="color:#e06c75">ff</span> <span style="color:#d19a66">43</span> <span style="color:#d19a66">00</span> <span style="color:#e06c75">d1</span> 	<span style="color:#e06c75">sub</span>	<span style="color:#e06c75">sp</span>, <span style="color:#e06c75">sp</span>, #<span style="color:#d19a66">16</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span><span style="color:#d19a66">100003f</span><span style="color:#d19a66">38</span><span style="color:#56b6c2">:</span> <span style="color:#e06c75">e0</span> <span style="color:#d19a66">0f</span> <span style="color:#d19a66">00</span> <span style="color:#e06c75">b9</span> 	<span style="color:#e06c75">str</span>	<span style="color:#e06c75">w0</span>, [<span style="color:#e06c75">sp</span>, #<span style="color:#d19a66">12</span>]
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span><span style="color:#d19a66">100003f</span><span style="color:#d19a66">3</span><span style="color:#e06c75">c</span>: <span style="color:#e06c75">e8</span> <span style="color:#d19a66">0f</span> <span style="color:#d19a66">40</span> <span style="color:#e06c75">b9</span> 	<span style="color:#e06c75">ldr</span>	<span style="color:#e06c75">w8</span>, [<span style="color:#e06c75">sp</span>, #<span style="color:#d19a66">12</span>]
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span><span style="color:#d19a66">100003f</span><span style="color:#d19a66">40</span><span style="color:#56b6c2">:</span> <span style="color:#d19a66">00</span> <span style="color:#d19a66">05</span> <span style="color:#d19a66">00</span> <span style="color:#d19a66">11</span> 	<span style="color:#e06c75">add</span>	<span style="color:#e06c75">w0</span>, <span style="color:#e06c75">w8</span>, #<span style="color:#d19a66">1</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span><span style="color:#d19a66">100003f</span><span style="color:#d19a66">44</span><span style="color:#56b6c2">:</span> <span style="color:#e06c75">ff</span> <span style="color:#d19a66">43</span> <span style="color:#d19a66">00</span> <span style="color:#d19a66">91</span> 	<span style="color:#e06c75">add</span>	<span style="color:#e06c75">sp</span>, <span style="color:#e06c75">sp</span>, #<span style="color:#d19a66">16</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7">7</a></span><span><span style="color:#d19a66">100003f</span><span style="color:#d19a66">48</span><span style="color:#56b6c2">:</span> <span style="color:#e06c75">c0</span> <span style="color:#d19a66">03</span> <span style="color:#d19a66">5f</span> <span style="color:#e06c75">d6</span> 	<span style="color:#e06c75">ret</span>
</span></span></code></pre></div><p>上述结果是我在arm64-apple-darwin21.6.0环境下，使用clang
14.0编译出来的结果，gcc编译的结果稍微有点区别，但是对于本文分析问题影响不大。</p>]]></description></item><item><title>使用std::list的splice方法实现LRU Cache</title><link>https://blog.liubang.cc/posts/cpp/2022-05-15-%E4%BD%BF%E7%94%A8stdlist%E7%9A%84splice%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0lru-cache/</link><pubDate>Sun, 15 May 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-05-15-%E4%BD%BF%E7%94%A8stdlist%E7%9A%84splice%E6%96%B9%E6%B3%95%E5%AE%9E%E7%8E%B0lru-cache/</guid><description><![CDATA[<h2 id="stdlist-splice-简介" data-numberify>std::list splice 简介<a class="anchor ms-1" href="#stdlist-splice-简介"></a></h2>
<p><code>splice</code>函数通过重新排列链表指针，将一个<code>std::list</code>中的节点转移到另一个<code>std::list</code>中。在元素的转移过程中不会触发元素的拷贝或者移动。因此，调用<code>splice</code>函数之后，元素现有的引用和迭代器都不会失效。</p>
<p>下面是一个将<code>listA</code>中所有节点附加到<code>listB</code>的一个简单代码示例，转移的过程不会导致<code>listA</code>中元素的引用和迭代器失效:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// Note: c++17 required below. (For CTAD(Class template argument deducation))
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">list</span> <span style="color:#e06c75">listA</span>{<span style="color:#d19a66">1</span>, <span style="color:#d19a66">2</span>, <span style="color:#d19a66">3</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">list</span> <span style="color:#e06c75">listB</span>{<span style="color:#d19a66">4</span>, <span style="color:#d19a66">5</span>, <span style="color:#d19a66">6</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#c678dd">auto</span> <span style="color:#e06c75">it</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">listA</span>.<span style="color:#e06c75">begin</span>();   <span style="color:#7f848e">// Iterator to 1
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#7f848e">// Append listA to listB
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span><span style="color:#e06c75">listB</span>.<span style="color:#e06c75">splice</span>(<span style="color:#e06c75">listB</span>.<span style="color:#e06c75">end</span>(), <span style="color:#e06c75">listA</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#7f848e">// All listA elements transferred to listB
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">listB</span>.<span style="color:#e06c75">size</span>() <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#34; &#34;</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">listA</span>.<span style="color:#e06c75">size</span>() <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">endl</span>;   <span style="color:#7f848e">// 6 0
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#7f848e">// Prints Below: 4 5 6 1 2 3
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span><span style="color:#c678dd">for</span> (<span style="color:#c678dd">auto</span> <span style="color:#e06c75">i</span> : <span style="color:#e06c75">listB</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#34; &#34;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span><span style="color:#7f848e">// Iterator still valid
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">it</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">endl</span>;   <span style="color:#7f848e">// 1
</span></span></span></code></pre></div><p>当然，我们也可以在不使用<code>splice</code>的情况下将一个 list 中的元素转移到另一个 list 中，但是需要将原 list 中的元素删除，并在目标 list 中插入新的元素。删除和新增元素对于较小的对象（例如 int）是可以接受的，但是对于较大的对象来说，由于需要调用拷贝/移动构造和析构函数，所以成本会很高。</p>]]></description></item><item><title>深入理解 enable_shared_from_this</title><link>https://blog.liubang.cc/posts/cpp/2022-05-03-%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3enable_shared_from_this/</link><pubDate>Tue, 03 May 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-05-03-%E6%B7%B1%E5%85%A5%E7%90%86%E8%A7%A3enable_shared_from_this/</guid><description><![CDATA[<h2 id="关于-shared_ptr" data-numberify>关于 shared_ptr<a class="anchor ms-1" href="#关于-shared_ptr"></a></h2>
<p><code>shared_ptr</code>是一种共享所有权的智能指针，它允许我们安全地访问和管理对象的生命周期。<code>shared_ptr</code>的多个实例通过共享控制块结构来控制对象的生命周期。
控制块维护了引用计数(reference count)，弱引用计数(weak count)和其他必要的信息，通过这些信息，控制块能够确定一个对象在内存中是否可以被安全销毁。</p>
<p>当使用原始指针构造或者初始化一个<code>shared_ptr</code>时，将会创建一个新的控制块。为了确保一个对象仅由一个共享的控制块管理，必须通过复制已存在的<code>shared_ptr</code>对象来创建一个新的<code>shared_ptr</code>实例，例如：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">good</span>()
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>  <span style="color:#c678dd">auto</span> <span style="color:#e06c75">p</span>{<span style="color:#c678dd">new</span> <span style="color:#e5c07b">int</span>(<span style="color:#d19a66">10</span>)}; <span style="color:#7f848e">// p is int*
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>  <span style="color:#7f848e">// create additional shared_ptr from an existing shared_ptr
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>  <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">shared_ptr</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">sp1</span>{<span style="color:#e06c75">p</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6">6</a></span><span>  <span style="color:#7f848e">// sp2 shares control block with sp1
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7">7</a></span><span>  <span style="color:#c678dd">auto</span> <span style="color:#e06c75">sp2</span>{<span style="color:#e06c75">sp1</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8">8</a></span><span>}
</span></span></code></pre></div><p>而使用指向已由<code>shared_ptr</code>管理的对象的原始指针来初始化另一个<code>shared_ptr</code>时，会创建一个新的控制块来管理该对象，
这样同一个对象就同时被多个控制块管理，这会导致 undefined behavior，例如：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">bad</span>()
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>  <span style="color:#c678dd">auto</span> <span style="color:#e06c75">p</span>{<span style="color:#c678dd">new</span> <span style="color:#e5c07b">int</span>(<span style="color:#d19a66">10</span>);};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>  <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">shared_ptr</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">sp1</span>{<span style="color:#e06c75">p</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span>  <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">shared_ptr</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">sp2</span>{<span style="color:#e06c75">p</span>}; <span style="color:#7f848e">// Undefined behavior!
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span>}
</span></span></code></pre></div><p>通过原始指针的方式实例化<code>shared_ptr</code>很容易产生同一个原始指针实例化多个<code>shared_ptr</code>这样的编码疏忽，从而造成严重后果。
因此尽量使用<code>std::make_shared</code>或者<code>std::allocate_shared</code>来降低出错的可能性。毕竟除非有人刻意为之，否则我们似乎很难遇到或写出这样的代码：</p>]]></description></item><item><title>c++ 中 unique_ptr 的一些使用技巧</title><link>https://blog.liubang.cc/posts/cpp/2022-04-20-c++%E4%B8%ADunique_ptr%E7%9A%84%E4%B8%80%E4%BA%9B%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/</link><pubDate>Wed, 20 Apr 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-04-20-c++%E4%B8%ADunique_ptr%E7%9A%84%E4%B8%80%E4%BA%9B%E4%BD%BF%E7%94%A8%E6%8A%80%E5%B7%A7/</guid><description><![CDATA[<h2 id="前言" data-numberify>前言<a class="anchor ms-1" href="#前言"></a></h2>
<p>c++11 对智能指针做了很大的优化，废弃了 c++98 中的<code>auto_ptr</code>，引入了三种新的智能指针：<code>unique_ptr</code>，<code>shared_ptr</code>，<code>weak_ptr</code>。
本文将针对<code>unique_ptr</code>的一些使用技巧做一些整理和归纳。在正式开始之前，我们首先来回顾一下<code>unique_ptr</code>的特点：一个<code>unique_ptr</code>对象内包含一个原始指针，该<code>unique_ptr</code>对象负责管理原始指针的生命周期。
一个<code>unique_ptr</code>对象始终是其关联的原始指针的唯一拥有者。</p>
<p>在了解了<code>unique_ptr</code>的特点之后，我们来具体看看日常开发中<code>unique_ptr</code>的一些使用场景和技巧。</p>

<h2 id="一些场景" data-numberify>一些场景<a class="anchor ms-1" href="#一些场景"></a></h2>

<h3 id="本地对象指针" data-numberify>本地对象指针<a class="anchor ms-1" href="#本地对象指针"></a></h3>
<p>在开发中，我们经常会遇到或者写出类似于下面这样的逻辑：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">somefunc</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>    <span style="color:#e06c75">Object</span> <span style="color:#e06c75">obj</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">new</span> <span style="color:#e06c75">Object</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>    <span style="color:#7f848e">// ...
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>    <span style="color:#c678dd">if</span> (<span style="color:#7f848e">/* event 1 */</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>        <span style="color:#c678dd">delete</span> <span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>        <span style="color:#c678dd">return</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#c678dd">if</span> (<span style="color:#7f848e">/* event 2 */</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>        <span style="color:#c678dd">delete</span> <span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>        <span style="color:#c678dd">return</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>    <span style="color:#c678dd">delete</span> <span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>}
</span></span></code></pre></div><p>对于这样的代码，写起来很麻烦，看上去也及其丑陋。以前我们常用的一种优化手段就是使用<code>goto</code>，而在 c++11 之后，我们有了一种更加优雅简洁的方式，来对上面的代码进行优化，那就是使用<code>unique_ptr</code>:</p>]]></description></item><item><title>Expression Templates</title><link>https://blog.liubang.cc/posts/cpp/2022-04-06-expression-templates/</link><pubDate>Wed, 06 Apr 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-04-06-expression-templates/</guid><description><![CDATA[<h2 id="什么是-expression-templates" data-numberify>什么是 Expression Templates<a class="anchor ms-1" href="#什么是-expression-templates"></a></h2>
<p>Expression Templates 是一种 C++ 模板元编程技术，它通过在编译时构建按需执行的计算表达式，从而生成高效的代码。简单来说，通过 Expression Templates，我们可以实现惰性求值和消除因为中间结果而创建的临时变量。</p>

<h2 id="一个常规示例" data-numberify>一个常规示例<a class="anchor ms-1" href="#一个常规示例"></a></h2>
<p>我们构造了一个<code>MyVector</code>类，并且重载了<code>MyVector</code>的<code>+</code>和<code>*</code>操作符，实现两个<code>MyVector</code>中相同下标元素的<code>+</code>和<code>*</code>操作。
对于这样的需求我们很容易写出形如下面代码的一个简单的实现：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;cassert&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;iostream&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;vector&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#c678dd">class</span> <span style="color:#e5c07b">MyVector</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e06c75">MyVector</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">n</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>        <span style="color:#56b6c2">:</span> <span style="color:#e06c75">vec_</span>(<span style="color:#e06c75">n</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    {}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>    <span style="color:#e06c75">MyVector</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">n</span>, <span style="color:#c678dd">const</span> <span style="color:#e06c75">T</span> <span style="color:#e06c75">initvalues</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>        <span style="color:#56b6c2">:</span> <span style="color:#e06c75">vec_</span>(<span style="color:#e06c75">n</span>, <span style="color:#e06c75">initvalues</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>    {}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">size</span>() <span style="color:#c678dd">const</span> { <span style="color:#c678dd">return</span> <span style="color:#e06c75">vec_</span>.<span style="color:#e06c75">size</span>(); }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>    <span style="color:#e06c75">T</span> <span style="color:#c678dd">operator</span>[](<span style="color:#c678dd">const</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">i</span>) <span style="color:#c678dd">const</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>    {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span>        <span style="color:#e06c75">assert</span>(<span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">size</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>        <span style="color:#c678dd">return</span> <span style="color:#e06c75">vec_</span>[<span style="color:#e06c75">i</span>];
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>    <span style="color:#e06c75">T</span><span style="color:#56b6c2">&amp;</span> <span style="color:#c678dd">operator</span>[](<span style="color:#c678dd">const</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">i</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>    {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span>        <span style="color:#e06c75">assert</span>(<span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">size</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span>        <span style="color:#c678dd">return</span> <span style="color:#e06c75">vec_</span>[<span style="color:#e06c75">i</span>];
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span><span style="color:#c678dd">private</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-30"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-30">30</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">vector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">vec_</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-31"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-31">31</a></span><span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-32"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-32">32</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-33"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-33">33</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#c678dd">operator</span><span style="color:#56b6c2">+</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;&amp;</span> <span style="color:#e06c75">a</span>, <span style="color:#c678dd">const</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;&amp;</span> <span style="color:#e06c75">b</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-34"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-34">34</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-35"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-35">35</a></span><span>    <span style="color:#e06c75">assert</span>(<span style="color:#e06c75">a</span>.<span style="color:#e06c75">size</span>() <span style="color:#56b6c2">==</span> <span style="color:#e06c75">b</span>.<span style="color:#e06c75">size</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-36"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-36">36</a></span><span>    <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">result</span>(<span style="color:#e06c75">a</span>.<span style="color:#e06c75">size</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-37"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-37">37</a></span><span>    <span style="color:#c678dd">for</span> (<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">a</span>.<span style="color:#e06c75">size</span>(); <span style="color:#56b6c2">++</span><span style="color:#e06c75">i</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-38"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-38">38</a></span><span>        <span style="color:#e06c75">result</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">=</span> <span style="color:#e06c75">a</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">+</span> <span style="color:#e06c75">b</span>[<span style="color:#e06c75">i</span>];
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-39"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-39">39</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-40"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-40">40</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#e06c75">result</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-41"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-41">41</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-42"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-42">42</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-43"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-43">43</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#c678dd">operator</span><span style="color:#56b6c2">*</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;&amp;</span> <span style="color:#e06c75">a</span>, <span style="color:#c678dd">const</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;&amp;</span> <span style="color:#e06c75">b</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-44"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-44">44</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-45"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-45">45</a></span><span>    <span style="color:#e06c75">assert</span>(<span style="color:#e06c75">a</span>.<span style="color:#e06c75">size</span>() <span style="color:#56b6c2">==</span> <span style="color:#e06c75">b</span>.<span style="color:#e06c75">size</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-46"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-46">46</a></span><span>    <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">result</span>(<span style="color:#e06c75">a</span>.<span style="color:#e06c75">size</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-47"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-47">47</a></span><span>    <span style="color:#c678dd">for</span> (<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">a</span>.<span style="color:#e06c75">size</span>(); <span style="color:#56b6c2">++</span><span style="color:#e06c75">i</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-48"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-48">48</a></span><span>        <span style="color:#e06c75">result</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">=</span> <span style="color:#e06c75">a</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">*</span> <span style="color:#e06c75">b</span>[<span style="color:#e06c75">i</span>];
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-49"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-49">49</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-50"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-50">50</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#e06c75">result</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-51"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-51">51</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-52"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-52">52</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-53"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-53">53</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">ostream</span><span style="color:#56b6c2">&amp;</span> <span style="color:#c678dd">operator</span><span style="color:#56b6c2">&lt;&lt;</span>(<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">ostream</span><span style="color:#56b6c2">&amp;</span> <span style="color:#e06c75">os</span>, <span style="color:#c678dd">const</span> <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;&amp;</span> <span style="color:#e06c75">vec</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-54"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-54">54</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-55"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-55">55</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#39;\n&#39;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-56"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-56">56</a></span><span>    <span style="color:#c678dd">for</span> (<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">size_t</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">vec</span>.<span style="color:#e06c75">size</span>(); <span style="color:#56b6c2">++</span><span style="color:#e06c75">i</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-57"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-57">57</a></span><span>        <span style="color:#e06c75">os</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">vec</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#39; &#39;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-58"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-58">58</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-59"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-59">59</a></span><span>    <span style="color:#e06c75">os</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#39;\n&#39;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-60"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-60">60</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#e06c75">os</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-61"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-61">61</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-62"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-62">62</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-63"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-63">63</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">argv</span>[])
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-64"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-64">64</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-65"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-65">65</a></span><span>    <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">double</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">x</span>(<span style="color:#d19a66">10</span>, <span style="color:#d19a66">5.4</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-66"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-66">66</a></span><span>    <span style="color:#e06c75">MyVector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">double</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">y</span>(<span style="color:#d19a66">10</span>, <span style="color:#d19a66">10.3</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-67"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-67">67</a></span><span>    <span style="color:#c678dd">auto</span>             <span style="color:#e06c75">ret</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">x</span> <span style="color:#56b6c2">+</span> <span style="color:#e06c75">x</span> <span style="color:#56b6c2">+</span> <span style="color:#e06c75">y</span> <span style="color:#56b6c2">*</span> <span style="color:#e06c75">y</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-68"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-68">68</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">ret</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-69"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-69">69</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-70"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-70">70</a></span><span>}
</span></span></code></pre></div><p>这个实现平淡无奇，相信每个人都能随手写出来。在<a href="https://godbolt.org/z/zTenMfe6G" target="_blank" rel="noopener noreferrer">godbolt<i class="fas fa-external-link-square-alt ms-1"></i></a>上编译成汇编来分析：</p>]]></description></item><item><title>c++中的动态多态和静态多态</title><link>https://blog.liubang.cc/posts/cpp/2022-03-23-c++%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E5%A4%9A%E6%80%81%E5%92%8C%E9%9D%99%E6%80%81%E5%A4%9A%E6%80%81/</link><pubDate>Wed, 23 Mar 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-03-23-c++%E4%B8%AD%E7%9A%84%E5%8A%A8%E6%80%81%E5%A4%9A%E6%80%81%E5%92%8C%E9%9D%99%E6%80%81%E5%A4%9A%E6%80%81/</guid><description><![CDATA[<h2 id="动态多态-dynamic-polymorphism" data-numberify>动态多态 (Dynamic Polymorphism)<a class="anchor ms-1" href="#动态多态-dynamic-polymorphism"></a></h2>
<p>在 c++中为了实现多态，使用了一种动态绑定的技术，这个技术的核心就是虚函数表(virtual table)。下面就简单的说明一下基于虚表的动态绑定的原理，从而更好的与静态多态做比较。</p>
<p>在 c++中，每个包含虚函数的类都有一个虚表。我们来看下面这个类：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// demo.cpp
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">A</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>    <span style="color:#c678dd">virtual</span> <span style="color:#e5c07b">void</span> <span style="color:#e06c75">vfunc1</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#c678dd">virtual</span> <span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">vfunc2</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e5c07b">void</span>         <span style="color:#61afef;font-weight:bold">func1</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e5c07b">void</span>         <span style="color:#61afef;font-weight:bold">func2</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#c678dd">private</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">m_data1</span>, <span style="color:#e06c75">m_data2</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>};
</span></span></code></pre></div><p>我们可以借助编译器来查看上述类的对象布局：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-bash" data-lang="bash"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#7f848e"># 使用llvm编译工具</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span>clang -Xclang -fdump-record-layouts -stdlib<span style="color:#56b6c2">=</span>libc++ -c demo.cpp <span style="color:#7f848e"># 查看对象布局</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>clang -Xclang -fdump-vtable-layouts -stdlib<span style="color:#56b6c2">=</span>libc++ -c demo.cpp <span style="color:#7f848e"># 查看虚表布局</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span><span style="color:#7f848e"># 使用gcc编译工具</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span>g++ -fdump-lang-class demo.cpp
</span></span></code></pre></div><p>这里为了便于分析，使用 clang 打印的结果来具体说明：</p>]]></description></item><item><title>c++17:constexpr if</title><link>https://blog.liubang.cc/posts/cpp/2022-03-18-c++17-constexpr_if/</link><pubDate>Fri, 18 Mar 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-03-18-c++17-constexpr_if/</guid><description><![CDATA[<p>constexpr 是 c++11 引入的关键字，用于编译时常量和常量表达式。而 c++17 将这一特性做了增强，引入了 <code>constexpr if</code> ，
使得编译器在编译时(compile time)能够做分支判断，从而有条件的编译代码。</p>
<p>下面可以通过一个简单的例子来看看<code>constexpr if</code>的用法：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;iostream&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;type_traits&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">typename</span> <span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#c678dd">auto</span> <span style="color:#e06c75">getValue</span>(<span style="color:#e06c75">T</span> <span style="color:#e06c75">t</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#c678dd">if</span> <span style="color:#61afef;font-weight:bold">constexpr</span> (<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">is_pointer</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&gt;::</span><span style="color:#e06c75">value</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>        <span style="color:#c678dd">return</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">t</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    } <span style="color:#c678dd">else</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>        <span style="color:#c678dd">return</span> <span style="color:#e06c75">t</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">argv</span>[])
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>    <span style="color:#e5c07b">int</span>  <span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">10</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>    <span style="color:#e5c07b">int</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">b</span> <span style="color:#56b6c2">=</span> <span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">a</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>    <span style="color:#e06c75">getValue</span>(<span style="color:#e06c75">a</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>    <span style="color:#e06c75">getValue</span>(<span style="color:#e06c75">b</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>}
</span></span></code></pre></div><p>其实和普通的条件判断区别不大，只不过<code>constexpr if</code>中的条件是常量表达式，可以在编译时确定条件表达式的结果，从而选择编译对应的分支代码。
我们可以将上述代码编译成汇编来进一步分析：</p>]]></description></item><item><title>c++20:Designated Initializers</title><link>https://blog.liubang.cc/posts/cpp/2022-03-15-c++20-designated_initializers/</link><pubDate>Tue, 15 Mar 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-03-15-c++20-designated_initializers/</guid><description><![CDATA[<p>对于熟悉 c99 的人来说，Designated Initializers 并不算是什么新鲜事物，然而 c++直到 c++20 才正式支持这一特性。
虽然在 c++20 之前，像 GCC 这样的编译器通过扩展的形式已经对该特性做了支持，但是随着 c++20 将其纳入新标准，这一特性将在所有编译器中得到支持。</p>

<h2 id="基本用法" data-numberify>基本用法<a class="anchor ms-1" href="#基本用法"></a></h2>
<p>Designated Initialization 是聚合初始化(Aggregate Initialization)的一种形式。
在 c++20 中，聚合类型(Aggregate types)是指：</p>
<ul>
<li>数组类型</li>
<li>具备如下特性的 class 类型：</li>
<li>
<ul>
<li>has no private or protected direct non-static data members</li>
</ul>
</li>
<li>
<ul>
<li>has no user-declared or inherited constructors</li>
</ul>
</li>
<li>
<ul>
<li>has no virtual, private, or protected base classes</li>
</ul>
</li>
<li>
<ul>
<li>has no virtual member functions</li>
</ul>
</li>
</ul>
<p>c++20 中的 Designated Initializers 的用法跟 c99 非常相似：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e5c07b">Points</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e5c07b">double</span> <span style="color:#e06c75">x</span>{<span style="color:#d19a66">0.0</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#e5c07b">double</span> <span style="color:#e06c75">y</span>{<span style="color:#d19a66">0.0</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6">6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7">7</a></span><span><span style="color:#c678dd">const</span> <span style="color:#e06c75">Points</span> <span style="color:#e06c75">p</span>{.<span style="color:#e06c75">x</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">1.1</span>, .<span style="color:#e06c75">y</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">2.2</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8">8</a></span><span><span style="color:#c678dd">const</span> <span style="color:#e06c75">Points</span> <span style="color:#e06c75">o</span>{.<span style="color:#e06c75">x</span>{<span style="color:#d19a66">1.1</span>}, .<span style="color:#e06c75">y</span>{<span style="color:#d19a66">2.2</span>}};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9">9</a></span><span><span style="color:#c678dd">const</span> <span style="color:#e06c75">Points</span> <span style="color:#e06c75">x</span>{.<span style="color:#e06c75">x</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">1.1</span>, .<span style="color:#e06c75">y</span>{<span style="color:#d19a66">2.2</span>}};
</span></span></code></pre></div>
<h2 id="优点" data-numberify>优点<a class="anchor ms-1" href="#优点"></a></h2>
<p>使用 Designated Initializers 最大的好处就是能够提升代码的可读性。</p>]]></description></item><item><title>Linux磁盘IO</title><link>https://blog.liubang.cc/posts/linux/2022-02-25-linux%E7%A3%81%E7%9B%98io/</link><pubDate>Fri, 25 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/linux/2022-02-25-linux%E7%A3%81%E7%9B%98io/</guid><description><![CDATA[<h2 id="前言" data-numberify>前言<a class="anchor ms-1" href="#前言"></a></h2>
<p>做存储开发，一定会经常涉及到 IO 相关的操作。而现在的高级编程语言，往往会帮助我们屏蔽 IO 操作的底层细节，虽然这样能降低开发门槛，提升效率，但是却也导致我们对 IO 底层操作实现的理解不够系统和深入。
所以呢，我一直想抽时间来系统整理一下 Linux IO 涉及的系统调用，以及相互之间的区别和联系，以加深对 IO 操作的理解。</p>

<h2 id="io-操作" data-numberify>IO 操作<a class="anchor ms-1" href="#io-操作"></a></h2>

<h3 id="fwrite" data-numberify>fwrite<a class="anchor ms-1" href="#fwrite"></a></h3>
<p>fwrite 是 c 语言标准库中的文件写入函数，其作用是向指定的文件中写入若干数据。调用 fwrite 实际上是将数据写入到了 c 标准库的 IO Buffer 中。</p>

<h3 id="mmap" data-numberify>mmap<a class="anchor ms-1" href="#mmap"></a></h3>
<p>mmap 将一个文件或者其它对象映射进内存。文件被映射到多个页上，如果文件的大小不是所有页的大小之和，最后一个页不被使用的空间将会清零。mmap 在用户空间映射调用系统中作用很大。</p>

<h3 id="fflush" data-numberify>fflush<a class="anchor ms-1" href="#fflush"></a></h3>
<p>fflush 就是将 c 标准库中的 IO Buffer 中的数据写入到参数 stream 指定的文件中。</p>

<h3 id="fsync" data-numberify>fsync<a class="anchor ms-1" href="#fsync"></a></h3>
<p>fsync 系统调用就是将内核缓冲区中的数据同步到存储介质(如硬盘)。也可以在 open 文件的时候通过开启<code>O_SYNC</code>来开启同步 I/O.</p>

<h2 id="各-io-操作的区别与联系" data-numberify>各 IO 操作的区别与联系<a class="anchor ms-1" href="#各-io-操作的区别与联系"></a></h2>
<p><picture><img class="img-fluid mx-auto d-block" alt="图片引用自 https://oscimg.oschina.net/oscnet/51a17cc9aa34eba47971af609fdecabf398.jpg" src="https://blog.liubang.cc/images/2022-02-28/linux_io_sub_system_arch.jpeg#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="1216" height="1224" />
</picture>

</p>]]></description></item><item><title>c++元编程之遍历tuple</title><link>https://blog.liubang.cc/posts/cpp/2022-02-22-c++%E5%85%83%E7%BC%96%E7%A8%8B%E4%B9%8B%E9%81%8D%E5%8E%86tuple/</link><pubDate>Tue, 22 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-02-22-c++%E5%85%83%E7%BC%96%E7%A8%8B%E4%B9%8B%E9%81%8D%E5%8E%86tuple/</guid><description><![CDATA[<p>对于一个标准的 c++容器来说，我们可以很容易在运行时使用迭代器和 range-based for
loop 来遍历其中的每一个元素。但是对于<code>std::tuple</code>，却不能像普通的容器那样去遍历它。</p>

<h2 id="stdtuple-简介" data-numberify>std::tuple 简介<a class="anchor ms-1" href="#stdtuple-简介"></a></h2>
<p><code>std::tuple</code>是一个具有固定大小，包含不同类型值的集和。与之相似的是<code>std::pair</code>，只不过<code>std::pair</code>只能容纳两个元素，
而<code>std::tuple</code>可以容纳许多元素：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">tuple</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span>, <span style="color:#e5c07b">double</span>, <span style="color:#c678dd">const</span> <span style="color:#e5c07b">char</span><span style="color:#56b6c2">*&gt;</span> <span style="color:#e06c75">tup</span> {<span style="color:#d19a66">42</span>, <span style="color:#d19a66">10.5</span>, <span style="color:#98c379">&#34;hello&#34;</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span><span style="color:#7f848e">// or with CTAD(class template argument deduction), C++17:
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">tuple</span> <span style="color:#e06c75">deducedTup</span> {<span style="color:#d19a66">42</span>, <span style="color:#d19a66">10.5</span>, <span style="color:#98c379">&#34;hello&#34;</span>}; <span style="color:#7f848e">// 自动推导类型
</span></span></span></code></pre></div><p>访问<code>std::pair</code>中的元素只需要访问<code>.first</code>和<code>.second</code>成员即可:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">pair</span> <span style="color:#e06c75">p</span> <span style="color:#56b6c2">=</span> {<span style="color:#d19a66">10</span>, <span style="color:#d19a66">10.5</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span><span style="color:#e06c75">p</span>.<span style="color:#e06c75">first</span> <span style="color:#56b6c2">+=</span> <span style="color:#d19a66">10</span>;
</span></span></code></pre></div><p>然而<code>std::tuple</code>并没有类似于<code>.first</code>
<code>.second</code>的成员，标准库中我们只能通过<code>std::get</code>来直接访问其中的元素:</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1"> 1</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">tuple</span> <span style="color:#e06c75">tp</span> {<span style="color:#d19a66">1</span>, <span style="color:#d19a66">2</span>, <span style="color:#98c379">&#34;hello&#34;</span>, <span style="color:#98c379">&#34;world&#34;</span>, <span style="color:#d19a66">10.5</span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-2"> 2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-3"> 3</a></span><span><span style="color:#7f848e">// by index
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-4"> 4</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">get</span><span style="color:#56b6c2">&lt;</span><span style="color:#d19a66">0</span><span style="color:#56b6c2">&gt;</span>(<span style="color:#e06c75">tp</span>) <span style="color:#56b6c2">+=</span> <span style="color:#d19a66">10</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-5"> 5</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">get</span><span style="color:#56b6c2">&lt;</span><span style="color:#d19a66">1</span><span style="color:#56b6c2">&gt;</span>(<span style="color:#e06c75">tp</span>) <span style="color:#56b6c2">*=</span> <span style="color:#d19a66">20</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-6"> 6</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">get</span><span style="color:#56b6c2">&lt;</span><span style="color:#d19a66">2</span><span style="color:#56b6c2">&gt;</span>(<span style="color:#e06c75">tp</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#39;\n&#39;</span>; <span style="color:#7f848e">// hello
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-7"> 7</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">get</span><span style="color:#56b6c2">&lt;</span><span style="color:#d19a66">3</span><span style="color:#56b6c2">&gt;</span>(<span style="color:#e06c75">tp</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#39;\n&#39;</span>; <span style="color:#7f848e">// world
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-8"> 8</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-9"> 9</a></span><span><span style="color:#7f848e">// by type
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-10">10</a></span><span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">get</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">double</span><span style="color:#56b6c2">&gt;</span>(<span style="color:#e06c75">tp</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#39;\n&#39;</span>; <span style="color:#7f848e">// 10.5
</span></span></span></code></pre></div>
<h2 id="如何遍历-tuple" data-numberify>如何遍历 tuple<a class="anchor ms-1" href="#如何遍历-tuple"></a></h2>
<p>对 tuple 有了初步的了解，也知道了如何去获取 tuple 中的元素，那么接下来我们就来一步步构造对 tuple 遍历的方法。</p>]]></description></item><item><title>c++17:string_view</title><link>https://blog.liubang.cc/posts/cpp/2022-02-14-c++17%E4%B9%8Bstring_view/</link><pubDate>Mon, 14 Feb 2022 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2022-02-14-c++17%E4%B9%8Bstring_view/</guid><description><![CDATA[<h2 id="string_view-简介" data-numberify>string_view 简介<a class="anchor ms-1" href="#string_view-简介"></a></h2>
<p><code>std::string_view</code>是 c++17 中新增的一种类型。其核心理念是，能够让我们在传统的 C++03 风格的具体性和泛型编程之间找到一个很好的折衷点。
在 C++17 标准之前，我们通常只能在粗糙的不严谨的模板实现和相对严谨但是有着冗长约束的模板之间做出选择。举个简单的例子：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// c++03 style
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">Widget</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span> <span style="color:#e06c75">name_</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e5c07b">void</span> <span style="color:#e06c75">setName</span>(<span style="color:#c678dd">const</span> <span style="color:#e5c07b">char</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">new_name</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">setName</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span><span style="color:#56b6c2">&amp;</span> <span style="color:#e06c75">new_name</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span><span style="color:#7f848e">// 不正确的欠约束的模板
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">Widget</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span> <span style="color:#e06c75">name_</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>    <span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">T</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e5c07b">void</span> <span style="color:#e06c75">setName</span>(<span style="color:#e06c75">T</span><span style="color:#56b6c2">&amp;&amp;</span> <span style="color:#e06c75">new_name</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>};
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span><span style="color:#7f848e">// 正确的但是约束但滑稽冗长的模板
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">Widget</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>    <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span> <span style="color:#e06c75">name_</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span>    <span style="color:#c678dd">template</span><span style="color:#56b6c2">&lt;</span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">T</span>, <span style="color:#c678dd">class</span> = <span style="color:#e5c07b">decltype</span>(<span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">declval</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">string</span><span style="color:#56b6c2">&amp;&gt;</span>() <span style="color:#56b6c2">=</span> <span style="color:#e06c75">std</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">declval</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">T</span><span style="color:#56b6c2">&amp;&amp;&gt;</span>()) <span style="color:#56b6c2">&gt;&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>                              <span style="color:#e5c07b">void</span> <span style="color:#e06c75">setName</span>(<span style="color:#e06c75">T</span><span style="color:#56b6c2">&amp;&amp;</span> <span style="color:#e06c75">new_name</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span>};
</span></span></code></pre></div><p>而有了 <code>string_view</code> 之后，以上代码就可以简化成如下：</p>]]></description></item><item><title>LevelDB 源码阅读之 Compaction</title><link>https://blog.liubang.cc/posts/storage/2021-01-12-leveldb%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E4%B9%8Bcompaction/</link><pubDate>Tue, 12 Jan 2021 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/storage/2021-01-12-leveldb%E6%BA%90%E7%A0%81%E9%98%85%E8%AF%BB%E4%B9%8Bcompaction/</guid><description><![CDATA[<h2 id="1-概览" data-numberify>1. 概览<a class="anchor ms-1" href="#1-概览"></a></h2>
<p>要谈论 LevelDB 的 Compaction 就不得不从 LevelDB 的整个数据写入流程入手。LevelDB 的基本写入流程大致为：</p>
<ol>
<li>数据先写入到 WAL 日志中，做持久化</li>
<li>然后数据同步到<code>mutable memtable</code>中</li>
<li>当<code>mutable memtable</code>大小达到<code>Options.write_buffer_size</code>设置的大小时，就会变成<code>immutable memtable</code>，并且创建一个新的<code>mutable memtable</code></li>
<li>后台的 Compaction 线程会把<code>immutable memtable</code>dump 成 sstable 文件，并设置于 Level 0 层</li>
<li>当 Level i 达到一定条件后，就会和 Level i + 1 层的 sstable 进行合并，从而触发 Compaction 过程，并在 Level
n + 1 层生成一个新的 sstable 文件</li>
</ol>

<h2 id="2-compaction-分类" data-numberify>2. Compaction 分类<a class="anchor ms-1" href="#2-compaction-分类"></a></h2>
<p>在 LevelDB 中，Compaction 大体上可以分为两类，分别是：</p>
<ul>
<li><code>immutable memtable compaction</code>，也叫做<strong>minor compaction</strong>，指的是将<code>immutable memtable</code>dump 到 sstable 文件的过程</li>
<li><code>sstable compaction</code>，也叫做<strong>major compaction</strong>，指的是 sstable 文件之间的合并过程</li>
</ul>
<p>而对于<code>sstable compaction</code>又可以细分为三种：</p>]]></description></item><item><title>分布式协议</title><link>https://blog.liubang.cc/posts/inf/2020-05-25-%E5%88%86%E5%B8%83%E5%BC%8F%E5%8D%8F%E8%AE%AE/</link><pubDate>Mon, 25 May 2020 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/inf/2020-05-25-%E5%88%86%E5%B8%83%E5%BC%8F%E5%8D%8F%E8%AE%AE/</guid><description><![CDATA[<h2 id="拜占庭将军问题" data-numberify>拜占庭将军问题<a class="anchor ms-1" href="#拜占庭将军问题"></a></h2>

<h3 id="简介" data-numberify>简介<a class="anchor ms-1" href="#简介"></a></h3>
<ul>
<li>在可能存在叛军的情况下，采用合适的通讯协议，让多个将军达成共识，执行统一的作战计划</li>
<li>二忠一叛难题</li>
<li>它是分布式领域最复杂的容错模型</li>
<li>莱斯利·兰伯特（Leslie Lamport）<a href="https://www.microsoft.com/en-us/research/uploads/prod/2016/12/The-Byzantine-Generals-Problem.pdf" target="_blank" rel="noopener noreferrer">The Byzantine Generals Problem<i class="fas fa-external-link-square-alt ms-1"></i></a></li>
</ul>

<h3 id="二忠一叛难题" data-numberify>二忠一叛难题<a class="anchor ms-1" href="#二忠一叛难题"></a></h3>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2020-05-25/bzt1.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="1035" height="575" />
</picture>

</p>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2020-05-25/bzt2.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="1100" height="569" />
</picture>

</p>
<ul>
<li>总共有三个将军，其中一个作为指挥官</li>
<li>通过信使相互传递作战指令，进攻或者撤退</li>
<li>所有忠诚的将军必须执行统一的作战计划，忠诚的将军必须执行忠诚的指挥官发布的指令</li>
<li>假如 LIEUTENANT2 叛变，LIEUTENANT1 收到的作战指令就是“进攻，撤退”</li>
<li>假如 COMMANDER 叛变，LIEUTENANT1 和 LIEUTENANT2 收到的作战指令都是“进攻，撤退”</li>
</ul>

<h3 id="口信消息型解法" data-numberify>口信消息型解法<a class="anchor ms-1" href="#口信消息型解法"></a></h3>
<ul>
<li>叛变人数为 m 需要已知</li>
<li>则所有参与者的人数至少为 3m+1</li>
<li>第一轮由指挥官发送作战指令</li>
<li>第二轮由各位将军相互发送指令</li>
<li>收到指令的将军按照少数服从多数的原则执行指令</li>
<li>按照这个公式，前面的例子叛军为 1 人的情况，则需要 1 个指挥官和 3 个将军</li>
</ul>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2020-05-25/bzt3.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="1181" height="529" />
</picture>

</p>
<p>假如 LIEUTENANT3 叛变了，那么首先指挥官向各位将军发送“进攻”的指令，由于 3 号将军叛变了，所以最终 1 号将军收到的指令是 2 个进攻，1 个撤退，2 号将军同样收到 2 个进攻，1 个撤退，这样忠诚的将军将会执行一致的指令</p>]]></description></item><item><title>基于公司私有gitlab的go module实践</title><link>https://blog.liubang.cc/posts/go/2019-10-17-%E5%9F%BA%E4%BA%8E%E5%85%AC%E5%8F%B8%E7%A7%81%E6%9C%89gitlab%E7%9A%84go-module%E5%AE%9E%E8%B7%B5/</link><pubDate>Thu, 17 Oct 2019 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/go/2019-10-17-%E5%9F%BA%E4%BA%8E%E5%85%AC%E5%8F%B8%E7%A7%81%E6%9C%89gitlab%E7%9A%84go-module%E5%AE%9E%E8%B7%B5/</guid><description><![CDATA[<h2 id="背景" data-numberify>背景<a class="anchor ms-1" href="#背景"></a></h2>
<p>我们 laser 存储为了更好的跟引擎对接，适应其他团队的技术生态，决定开发一套 golang 的公共库来给大家使用。于是我们在公司私有的 gitlab 上新建了一个项目:git.yourcomp.com/ad/ads_core/adgo，并且我们想使用单一的 codebase 来管理所有的公共 library.</p>
<p>而且，为了更好的管理模块，我们统一使用了 go mod。</p>
<p>按照平时我们在 github 上拉取 go library 的惯例，我本以为直接使用<code>go get git.yourcomp.com/ad/ads_core/adgo/xxx</code>就能直接拉取到相应的模块了，然而在开发完功能测试的时候却发现，事实并不是想象中那样。</p>

<h2 id="遇到的问题和解决方案" data-numberify>遇到的问题和解决方案<a class="anchor ms-1" href="#遇到的问题和解决方案"></a></h2>

<h3 id="1-仓库问题" data-numberify>1. 仓库问题<a class="anchor ms-1" href="#1-仓库问题"></a></h3>
<p>执行<code>go get</code>后，实际上会请求&quot;https://git.yourcomp.com/ad/ads_core/adgo?go-get=1&quot;这个地址，如果使用<code>-insecure</code>选项，则会请求&quot;http://git.yourcomp.com/ad/ads_core/adgo?go-get=1&quot;，正常情况下回返回meta tag：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-html" data-lang="html"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span>&lt;<span style="color:#e06c75">html</span>&gt;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>  &lt;<span style="color:#e06c75">head</span>&gt;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    &lt;<span style="color:#e06c75">meta</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>      <span style="color:#e06c75">name</span><span style="color:#56b6c2">=</span><span style="color:#98c379">&#34;go-import&#34;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>      <span style="color:#e06c75">content</span><span style="color:#56b6c2">=</span><span style="color:#98c379">&#34;git.yourcomp.com/ad/ads_core git http://git.yourcomp.com/ad/ads_core.git&#34;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6">6</a></span><span>    /&gt;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7">7</a></span><span>  &lt;/<span style="color:#e06c75">head</span>&gt;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8">8</a></span><span>&lt;/<span style="color:#e06c75">html</span>&gt;
</span></span></code></pre></div><p>这是 go remote import 的协议，meta tag 的格式一般为</p>]]></description></item><item><title>使用c语言模拟lisp语法</title><link>https://blog.liubang.cc/posts/sp/2019-08-18-c%E8%AF%AD%E8%A8%80%E6%A8%A1%E6%8B%9Flisp%E8%AF%AD%E6%B3%95/</link><pubDate>Sun, 18 Aug 2019 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2019-08-18-c%E8%AF%AD%E8%A8%80%E6%A8%A1%E6%8B%9Flisp%E8%AF%AD%E6%B3%95/</guid><description><![CDATA[<p>使用 c 语言的 macro 操作，能够很简单的用 c 语言模拟 lisp 语法。</p>

<h3 id="下面我们来定义-lisph-头文件" data-numberify>下面我们来定义 lisp.h 头文件<a class="anchor ms-1" href="#下面我们来定义-lisph-头文件"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#ifndef LISP_H_OTE1HWPK
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#define LISP_H_OTE1HWPK
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdlib.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#7f848e">#define define(ret, name, args, block) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span><span style="color:#7f848e">    ret name args { return block; }
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#7f848e">#define if(expr, block1, block2) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span><span style="color:#7f848e">    expr ? block1 : block2
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#7f848e">#define eq(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span><span style="color:#7f848e">    a == b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span><span style="color:#7f848e">#define neq(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span><span style="color:#7f848e">    a != b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span><span style="color:#7f848e">#define sub(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span><span style="color:#7f848e">    a - b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span><span style="color:#7f848e">#define mul(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span><span style="color:#7f848e">    a * b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span><span style="color:#7f848e">#define add(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span><span style="color:#7f848e">    a + b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span><span style="color:#7f848e">#define div(a, b) \
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span><span style="color:#7f848e">    a / b
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-30"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-30">30</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-31"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-31">31</a></span><span><span style="color:#7f848e">#endif </span><span style="color:#7f848e">/* end of include guard: LISP_H_OTE1HWPK */</span><span style="color:#7f848e">
</span></span></span></code></pre></div>
<h3 id="然后来用类似于-lisp-的语法编写一段求阶乘的代码" data-numberify>然后来用类似于 lisp 的语法编写一段求阶乘的代码：<a class="anchor ms-1" href="#然后来用类似于-lisp-的语法编写一段求阶乘的代码"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#61afef;font-weight:bold">define</span>(<span style="color:#e5c07b">int</span>, <span style="color:#e06c75">factorial</span>, (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">n</span>),
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span>       <span style="color:#c678dd">if</span>(<span style="color:#61afef;font-weight:bold">eq</span>(<span style="color:#e06c75">n</span>, <span style="color:#d19a66">0</span>),
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>          <span style="color:#d19a66">1</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>          <span style="color:#61afef;font-weight:bold">mul</span>(<span style="color:#e06c75">n</span>, <span style="color:#61afef;font-weight:bold">factorial</span>(<span style="color:#61afef;font-weight:bold">sub</span>(<span style="color:#e06c75">n</span>, <span style="color:#d19a66">1</span>)))))
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span><span style="color:#61afef;font-weight:bold">define</span>(<span style="color:#e5c07b">int</span>, <span style="color:#e06c75">main</span>, (<span style="color:#e5c07b">void</span>),
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7">7</a></span><span>       (<span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;10! = %d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#61afef;font-weight:bold">factorial</span>(<span style="color:#d19a66">10</span>)), <span style="color:#e06c75">EXIT_SUCCESS</span>))
</span></span></code></pre></div>
<h3 id="编写-makefile" data-numberify>编写 Makefile:<a class="anchor ms-1" href="#编写-makefile"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a></span><span>CFLAGS = -Wall -include &#34;lisp.h&#34;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-2">2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-3">3</a></span><span>TARGET=factorial
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-4">4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-5">5</a></span><span>all:
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-6">6</a></span><span>	gcc -o $(TARGET) $(TARGET).c $(CFLAGS)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-7">7</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-8">8</a></span><span>clean:
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-9">9</a></span><span>	rm -f $(TARGET)
</span></span></code></pre></div>
<h3 id="编译并运行" data-numberify>编译并运行：<a class="anchor ms-1" href="#编译并运行"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-1">1</a></span><span>liubang@venux-dev:~$ make
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-2">2</a></span><span>gcc -o factorial factorial.c -Wall -include &#34;lisp.h&#34;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-3">3</a></span><span>liubang@venux-dev:~$ ./factorial
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-4">4</a></span><span>10! = 3628800
</span></span></code></pre></div>]]></description></item><item><title>动态连接器技巧之使用LD_PRELOAD改变程序的行为</title><link>https://blog.liubang.cc/posts/sp/2019-07-18-%E5%8A%A8%E6%80%81%E8%BF%9E%E6%8E%A5%E5%99%A8%E6%8A%80%E5%B7%A7%E4%B9%8B%E4%BD%BF%E7%94%A8ld_preload%E6%94%B9%E5%8F%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E8%A1%8C%E4%B8%BA/</link><pubDate>Thu, 18 Jul 2019 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2019-07-18-%E5%8A%A8%E6%80%81%E8%BF%9E%E6%8E%A5%E5%99%A8%E6%8A%80%E5%B7%A7%E4%B9%8B%E4%BD%BF%E7%94%A8ld_preload%E6%94%B9%E5%8F%98%E7%A8%8B%E5%BA%8F%E7%9A%84%E8%A1%8C%E4%B8%BA/</guid><description><![CDATA[<p>我们有这样一段简单的代码，用来输出 10 个[0, 100)的随机数：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// random.c
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdlib.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;time.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#61afef;font-weight:bold">srand</span>(<span style="color:#61afef;font-weight:bold">time</span>(<span style="color:#e5c07b">NULL</span>));
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">10</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#c678dd">while</span> (<span style="color:#e06c75">i</span><span style="color:#56b6c2">--</span>) <span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;%d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#61afef;font-weight:bold">rand</span>() <span style="color:#56b6c2">%</span> <span style="color:#d19a66">100</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>}
</span></span></code></pre></div><p>编译运行：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-shell" data-lang="shell"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span>liubang@venux-dev:~$ gcc random.c -o random
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>liubang@venux-dev:~$ ./random
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span><span style="color:#d19a66">44</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span><span style="color:#d19a66">46</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span><span style="color:#d19a66">97</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span><span style="color:#d19a66">51</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span><span style="color:#d19a66">62</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span><span style="color:#d19a66">76</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span><span style="color:#d19a66">92</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span><span style="color:#d19a66">76</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span><span style="color:#d19a66">38</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span><span style="color:#d19a66">10</span>
</span></span></code></pre></div><p>这个程序每次运行的结果都是不一样的，现在我们希望我们能够在不修改源码的情况下，控制程序的输出结果，例如我希望这段程序运行的结果是
每次都能输出 10 个 10。由于不能修改源码，或者我们根本没有源码，面对这样一个编译后的可执行二进制文件，想要修改程序的运行结果，可能显
得有些困难。然而，如果能够善用动态连接器的话，这都不是问题。</p>]]></description></item><item><title>Spring Boot With BDD</title><link>https://blog.liubang.cc/posts/java/2019-03-15-spring_boot_with_bdd/</link><pubDate>Fri, 15 Mar 2019 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/java/2019-03-15-spring_boot_with_bdd/</guid><description><![CDATA[<h2 id="什么是-bdd" data-numberify>什么是 BDD<a class="anchor ms-1" href="#什么是-bdd"></a></h2>
<p>BDD(Behavior Driven Development)，行为驱动开发，是一种敏捷软件开发的技术，它鼓励软件项目中的开发者、QA 和非技术人员或商业参与者之间的协作。</p>
<p>BDD 的重点是通过与利益相关者的讨论取得对预期的软件行为的清醒认识。它通过用自然语言书写非程序员可读的测试用例扩展了测试驱动开发方法。行为驱动开发人员使用混合了领域中统一的语言的母语语言来描述他们的代码的目的。这让开发者得以把精力集中在代码应该怎么写，而不是技术细节上，而且也最大程度的减少了将代码编写者的技术语言与商业客户、用户、利益相关者、项目管理者等的领域语言之间来回翻译的代价。</p>

<h2 id="具体怎么操作" data-numberify>具体怎么操作<a class="anchor ms-1" href="#具体怎么操作"></a></h2>
<p>结合我们项目开发使用的 spring boot 2.x，下面我们来具体说明如何在实际项目中使用 BDD。</p>

<h3 id="依赖的包" data-numberify>依赖的包<a class="anchor ms-1" href="#依赖的包"></a></h3>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-xml" data-lang="xml"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#e06c75">&lt;cucumber.version&gt;</span>4.2.5<span style="color:#e06c75">&lt;/cucumber.version&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>...
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#e06c75">&lt;dependency&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#e06c75">&lt;groupId&gt;</span>io.cucumber<span style="color:#e06c75">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e06c75">&lt;artifactId&gt;</span>cucumber-junit<span style="color:#e06c75">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e06c75">&lt;version&gt;</span>${cucumber.version}<span style="color:#e06c75">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#e06c75">&lt;scope&gt;</span>test<span style="color:#e06c75">&lt;/scope&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#e06c75">&lt;/dependency&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span><span style="color:#e06c75">&lt;dependency&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>    <span style="color:#e06c75">&lt;groupId&gt;</span>io.cucumber<span style="color:#e06c75">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>    <span style="color:#e06c75">&lt;artifactId&gt;</span>cucumber-java<span style="color:#e06c75">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>    <span style="color:#e06c75">&lt;version&gt;</span>${cucumber.version}<span style="color:#e06c75">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>    <span style="color:#e06c75">&lt;scope&gt;</span>test<span style="color:#e06c75">&lt;/scope&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span><span style="color:#e06c75">&lt;/dependency&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span><span style="color:#e06c75">&lt;dependency&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>    <span style="color:#e06c75">&lt;groupId&gt;</span>io.cucumber<span style="color:#e06c75">&lt;/groupId&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>    <span style="color:#e06c75">&lt;artifactId&gt;</span>cucumber-spring<span style="color:#e06c75">&lt;/artifactId&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>    <span style="color:#e06c75">&lt;version&gt;</span>${cucumber.version}<span style="color:#e06c75">&lt;/version&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>    <span style="color:#e06c75">&lt;scope&gt;</span>test<span style="color:#e06c75">&lt;/scope&gt;</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span><span style="color:#e06c75">&lt;/dependency&gt;</span>
</span></span></code></pre></div>
<h3 id="定义启动文件" data-numberify>定义启动文件<a class="anchor ms-1" href="#定义启动文件"></a></h3>
<p>BDD 其实也是依赖 junit，然后调用<code>Cucumber</code>的 Runner 来运行相应的测试。</p>]]></description></item><item><title>多线程编程</title><link>https://blog.liubang.cc/posts/sp/2018-12-05-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B/</link><pubDate>Wed, 05 Dec 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2018-12-05-%E5%A4%9A%E7%BA%BF%E7%A8%8B%E7%BC%96%E7%A8%8B/</guid><description><![CDATA[<h2 id="开始之前" data-numberify>开始之前<a class="anchor ms-1" href="#开始之前"></a></h2>
<p>这篇文章主要是为了帮助大家熟悉 POSIX 线程库以及在实际开发中使用它的特性。我们会具体讲解如何利用这个线程库定义的不同工具
来解决编程中的问题。当然这里隐含了一个假设，就是读者已经了解过并行编程（或者多进程）的相关概念，如果没有这些背景知识
的话，读者可能会感觉到很难理解。不过也没关系，我的另一篇教程里边有专门为只具备线性编程思维的读者提供了对并行编程理论
和相关术语的讲解。</p>
<p>同样的，我假设聪明的你已经熟悉了异步编程模型，那些经常使用桌面环境的人会更容易去接受多线程编程的理念。</p>
<p>当我们谈到 POSIX 线程的时候，肯定会有人心生疑惑：“我们应该使用哪个标准下的 POSIX 线程？”。由于 POSIX 线程标准已经修订了好
多年，人们会发现，依据不同标准的实现有不同的函数集，不同的默认值和不同的细微差别。所以在此说明的是，本教程使用的是 v0.5 版的 Linux 内核中的线程库，使用其他操作系统和使用其他版本的读者，需要阅读一下你们对应的系统文档来同本文中的实例进行对应。同时，有些示例代码中使用到了阻塞式的系统调用，它们不能再用户级的线程库中很好的工作（参考另一篇文章：<a href="http://www.actcom.co.il/~choo/lupg/tutorials/parallel-programming-theory/parallel-programming-theory.html#multi_thread_lib" target="_blank" rel="noopener noreferrer">parallel programming theory tutorial<i class="fas fa-external-link-square-alt ms-1"></i></a> 来获取详细信息）。好了，说了那么多，主要是为了能保证文章中的示例代码能够在其他系统中正常使用，从而提高跨平台性。</p>

<h2 id="什么是线程为什么要使用线程" data-numberify>什么是线程？为什么要使用线程？<a class="anchor ms-1" href="#什么是线程为什么要使用线程"></a></h2>
<p>线程是一个迷你版的进程，它们拥有自己的栈，能够执行给定的一段代码。但是不同于进程的是，线程通常与其他线程共享记忆体（而
每个进程都拥有一个独立的记忆体区域）。一个线程组就是一个执行相同代码的线程的集合，他们共用记忆体，可以访问相同的全局变
量，拥有同样的文件描述符等等，他们以并行的方式执行（可能是时间片的方式，或者对于多核心系统，他们会真正平行执行）。</p>
<p>使用线程组而不是普通顺序执行程序的好处是多个操作可以同时进行，当一些事件产生的时候，他们能立马被处理（例如：如果我们有
一个线程处理用户接口，另一个线程处理数据库查询，那么我们可以在处理很多用户查询的同时，依然能够响应用户的输入）。</p>
<p>使用线程组而不是进程组的好处是线程间的上下文切换要比进程间的上下文切换要快很多（上下文切换是指系统从一个正在运行的线程或进程切换到去执行另一个线程或进程）。此外，线程间的通信也远远比进程间通信要高效很多。</p>
<p>线程编程有利也有弊，由于线程组共享记忆体，如果一个线程破坏了记忆体，那么其他线程也要受到牵连。但是进程就不同了，操作系
统会将进程之间隔离开，如果一个进程破坏了它的记忆体，那么其他进程不会受到影响。使用进程的另一个好处是，不同的进程可以运
行在不同的机器上，但是线程必须运行在同一台机器上（至少通常情况下是这样的）。</p>

<h2 id="创建和销毁线程" data-numberify>创建和销毁线程<a class="anchor ms-1" href="#创建和销毁线程"></a></h2>
<p>当一个多线程程序启动执行到<code>main()</code>函数的时候，就会有一个线程运行，这是一个全程线程（full-fledged thread，或者叫主线程），如果想创建一个新的线程，程序中需要使用<code>pthread_create()</code>函数</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;stdio.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;pthread.h&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">do_loop</span>(<span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">data</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span>; <span style="color:#7f848e">// counter, to print numbers
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">j</span>; <span style="color:#7f848e">// counter, for delay
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">me</span> <span style="color:#56b6c2">=</span> <span style="color:#56b6c2">*</span>((<span style="color:#e5c07b">int</span> <span style="color:#56b6c2">*</span>)<span style="color:#e06c75">data</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#c678dd">for</span> (<span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#d19a66">10</span>; <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>        <span style="color:#c678dd">for</span> (<span style="color:#e06c75">j</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">j</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#d19a66">50000</span>; <span style="color:#e06c75">j</span><span style="color:#56b6c2">++</span>) <span style="color:#7f848e">// delay loop
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>            ;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>        <span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;&#39;%d&#39; - Got &#39;%d&#39;</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#e06c75">me</span>, <span style="color:#e06c75">i</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>    <span style="color:#7f848e">// terminate the thread
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>    <span style="color:#61afef;font-weight:bold">pthread_exit</span>(<span style="color:#e5c07b">NULL</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">argv</span>[])
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>    <span style="color:#e5c07b">int</span>       <span style="color:#e06c75">thr_id</span>;    <span style="color:#7f848e">// thread ID for the newly created thread
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>    <span style="color:#e5c07b">pthread_t</span> <span style="color:#e06c75">p_thread</span>;  <span style="color:#7f848e">// thread&#39;s structure
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">1</span>;           <span style="color:#7f848e">// thread 1 identifying number
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">b</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">2</span>;           <span style="color:#7f848e">// thread 2 identifying number
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span>    <span style="color:#7f848e">// create a new thread that will execute &#39;do_loop()&#39;
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>    <span style="color:#e06c75">thr_id</span> <span style="color:#56b6c2">=</span> <span style="color:#61afef;font-weight:bold">pthread_create</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">p_thread</span>, <span style="color:#e5c07b">NULL</span>, <span style="color:#e06c75">do_loop</span>, (<span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span>)<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">a</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span>    <span style="color:#7f848e">// run &#39;do_loop&#39; in the main thread as well
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-30"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-30">30</a></span><span>    <span style="color:#61afef;font-weight:bold">do_loop</span>((<span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span>)<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">b</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-31"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-31">31</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-32"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-32">32</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-33"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-33">33</a></span><span>}
</span></span></code></pre></div><p>上述这段代码需要特殊说明的是：</p>]]></description></item><item><title>使用正则表达式开发一个高性能路由</title><link>https://blog.liubang.cc/posts/php/2018-04-16-%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BC%80%E5%8F%91%E4%B8%80%E4%B8%AA%E9%AB%98%E6%80%A7%E8%83%BD%E8%B7%AF%E7%94%B1/</link><pubDate>Mon, 16 Apr 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2018-04-16-%E4%BD%BF%E7%94%A8%E6%AD%A3%E5%88%99%E8%A1%A8%E8%BE%BE%E5%BC%8F%E5%BC%80%E5%8F%91%E4%B8%80%E4%B8%AA%E9%AB%98%E6%80%A7%E8%83%BD%E8%B7%AF%E7%94%B1/</guid><description><![CDATA[<p>原文地址：<a href="http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html" target="_blank" rel="noopener noreferrer">http://nikic.github.io/2014/02/18/Fast-request-routing-using-regular-expressions.html<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
<p>前一些日子，我发现了一个叫做<a href="https://github.com/c9s/Pux" target="_blank" rel="noopener noreferrer">Pux<i class="fas fa-external-link-square-alt ms-1"></i></a>的路由库，这个路由库声称自己比现有的路由要快很多，为了实现这个特点，该库使用了 C 语言编写了 PHP 扩展。</p>
<p>然而，当我瞅了几眼它的代码后，我非常怀疑这个库在路由过程中做了错误的优化，而且我能够很容易在不适用扩展的情况下做出更高性能的实现。
当我在看了 benchmarking 代码后更加确定了我的怀疑，因为我发现这里仅仅只是对及其确定的单个路由做了测试。</p>
<p>为了进一步研究这个问题，我写了一个轻量的路由库：<a href="https://github.com/nikic/FastRoute" target="_blank" rel="noopener noreferrer">FastRoute<i class="fas fa-external-link-square-alt ms-1"></i></a>。这个库中实现的分发过程接下来我会具体描述。为了给出一些前期印象，这里先给出一个
同 Pux 库的 benchmark 结果：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-fallback" data-lang="fallback"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span>1 placeholder  | Pux (no ext) | Pux (ext) | FastRoute
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>-----------------------------------------------------
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>First route    | 0.17 s       | 0.13 s    | 0.14 s
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>Last route     | 2.51 s       | 1.20 s    | 0.49 s
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>Unknown route  | 2.34 s       | 1.10 s    | 0.34 s
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>9 placeholders | Pux (no ext) | Pux (ext) | FastRoute
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>-----------------------------------------------------
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>First route    | 0.22 s       | 0.19 s    | 0.20 s
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>Last route     | 2.65 s       | 1.78 s    | 0.59 s
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>Unknown route  | 2.50 s       | 1.49 s    | 0.40 s
</span></span></code></pre></div><p>这个 benchmark 使用了 100 个路由，分别对最好和最坏的情况做了测试。而且分两个方面进行：一个是只包含一个占位符的路由，另一个是包含 9 个占位符的路由。整个过程
重复了上千次。</p>]]></description></item><item><title>c++编程之标准库和STL</title><link>https://blog.liubang.cc/posts/cpp/2018-03-19-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%A0%87%E5%87%86%E5%BA%93%E5%92%8Cstl/</link><pubDate>Mon, 19 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-03-19-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%A0%87%E5%87%86%E5%BA%93%E5%92%8Cstl/</guid><description><![CDATA[<h2 id="1-c标准库" data-numberify>1. C++标准库<a class="anchor ms-1" href="#1-c标准库"></a></h2>
<p>C++提供了很多库：</p>
<ol>
<li>标准 ANSI C 库都可以移植到 C++中。不同于 ANSI C 库的是，C++中需要在库名前加上&quot;c&quot;前缀，而且去掉&quot;.h&quot;，例如<code>&lt;cmath&gt;</code>对应于 C 语言就是<code>&lt;math.h&gt;</code>，<code>&lt;cstdlib&gt;</code>对应于 C 语言的<code>&lt;stlib.h&gt;</code></li>
<li>C++新增的库，例如 <code>&lt;iostream&gt;</code>，<code>&lt;iomanip&gt;</code>，<code>&lt;string&gt;</code>，<code>&lt;fstream&gt;</code>，<code>&lt;sstream&gt;</code></li>
<li>C++STL：包括容器，迭代器，算法和函数对象</li>
<li>Boost C++库</li>
</ol>

<h3 id="11-c-库和相关头文件" data-numberify>1.1 C 库和相关头文件<a class="anchor ms-1" href="#11-c-库和相关头文件"></a></h3>
<ul>
<li><code>&lt;cstring&gt;</code>：待会解释</li>
<li><code>&lt;cmath&gt;</code>：数学计算相关的库</li>
<li><code>&lt;cstdlib&gt;</code>：通用工具，例如异常（abort, exit, EXIT_SUCCESS, EXIT_FAILURE）；环境相关（getenv）；动态内存管理（malloc, free, calloc, realloc），字符解析（atoi, atof, atol, strtod），
伪随机序列生成（rand, srand, RAND_MAX）；数组搜索和排序（bsearch, qsort）</li>
<li><code>&lt;cctype&gt;</code>：字符类型检测（isalpha, isdigit, isalnum, isspace, isupper, islower, isblank, iscntrl, isgraph, isprint, ispunct, isxdigit）和字符转换（toupper, tolower）</li>
<li><code>&lt;climits&gt;</code>, <code>&lt;cfloat&gt;</code>：Size and limit of integer types (INT_MAX, INT_MIN, UINT_MAX, CHAR_BIT; and SHRT_XXX for short, LONG_XXX for long, LLONG_XXX for long long, CHAR_XXX for char) and floating-point types (DBL_MIN, DBL_MAX, DBL_DIG, DBL_MIN_EXP, DBL_MAX_EXP; and FLT_XXX for float, LDBL_XXX for long double)</li>
<li><code>&lt;ctime&gt;</code>：time, difftime, clock, gmttime, localtime, and etc.</li>
<li><code>&lt;cstdio&gt;</code>: C&rsquo;s IO operations (scanf, printf, fscanf, fprintf, fopen, fclose, etc)</li>
<li><code>&lt;cassert&gt;</code>, <code>&lt;cerrno&gt;</code>, <code>csignal&gt;</code>: 断言和错误</li>
<li><code>&lt;clocale&gt;</code>：本地化</li>
<li><code>&lt;cstdbool&gt;</code>, <code>&lt;cstdint&gt;</code>, <code>&lt;cstddef&gt;</code>, <code>&lt;cstdarg&gt;</code>:</li>
<li><code>&lt;cuchar&gt;</code>, <code>&lt;cwchar&gt;</code>, <code>&lt;cwcchar&gt;</code>: Unicode 字符</li>
</ul>

<h3 id="12-c库和相关头文件" data-numberify>1.2 C++库和相关头文件<a class="anchor ms-1" href="#12-c库和相关头文件"></a></h3>
<ul>
<li><code>&lt;ios&gt;, &lt;iostream&gt;, &lt;istream&gt;, &lt;ostream&gt;, &lt;fstream&gt;, &lt;sstream&gt;</code></li>
<li><code>&lt;iomanip&gt;</code></li>
<li><code>&lt;string&gt;</code></li>
<li><code>&lt;regex&gt;</code></li>
<li><code>&lt;random&gt;</code></li>
<li><code>&lt;limits&gt;</code></li>
<li><code>&lt;stdexception&gt;, &lt;exception&gt;</code></li>
<li><code>&lt;complex&gt;, &lt;tuple&gt;, &lt;valarry&gt;</code></li>
<li><code>&lt;locale&gt;</code></li>
<li><code>&lt;typeinfo&gt;</code></li>
<li><code>&lt;chrono&gt;</code></li>
<li>其它：<code>&lt;codecvt&gt;, &lt;new&gt;, &lt;ratio&gt;, &lt;system_error&gt;, &lt;type_traits&gt;</code></li>
</ul>

<h3 id="13-c-stl-和相关头文件" data-numberify>1.3 C++ STL 和相关头文件<a class="anchor ms-1" href="#13-c-stl-和相关头文件"></a></h3>
<p>STL 主要由以下头文件提供：</p>]]></description></item><item><title>c++编程之字符和字符串</title><link>https://blog.liubang.cc/posts/cpp/2018-03-15-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E5%AD%97%E7%AC%A6%E5%92%8C%E5%AD%97%E7%AC%A6%E4%B8%B2/</link><pubDate>Thu, 15 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-03-15-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E5%AD%97%E7%AC%A6%E5%92%8C%E5%AD%97%E7%AC%A6%E4%B8%B2/</guid><description><![CDATA[<h2 id="1-字符" data-numberify>1. 字符<a class="anchor ms-1" href="#1-字符"></a></h2>

<h3 id="11-字符类型库头文件cctype" data-numberify>1.1 字符类型库：头文件"cctype"<a class="anchor ms-1" href="#11-字符类型库头文件cctype"></a></h3>
<p>在头文件<code>&lt;cctype&gt;</code>（相当于 C 语言中的<code>&lt;ctype.h&gt;</code>），包含了一下字符处理函数：</p>
<table>
  <thead>
      <tr>
          <th>FUNCTION</th>
          <th>EXAMPLE</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>int isalpha(int ch);//如果 ch 是字母，返回 1，否则 0</td>
          <td></td>
      </tr>
      <tr>
          <td>int isdigit(int ch);//如果 ch 是数字，返回 1，否则 0</td>
          <td></td>
      </tr>
      <tr>
          <td>int isalnum(int ch);//如果 ch 是字母或数字，返回 1，否则 0</td>
          <td></td>
      </tr>
      <tr>
          <td>int isxdigit(int ch);//如果 ch 是十六进制数字[0-9A-Fa-f]，返回 1</td>
          <td></td>
      </tr>
      <tr>
          <td>int isupper(int ch);//如果 ch 是大写字母，返回 1</td>
          <td></td>
      </tr>
      <tr>
          <td>int islower(int ch);//如果 ch 是小写字母，返回 1</td>
          <td></td>
      </tr>
      <tr>
          <td>int toupper(int ch);//转成大写字母</td>
          <td></td>
      </tr>
      <tr>
          <td>int tolower(int ch);//转成小写</td>
          <td></td>
      </tr>
      <tr>
          <td>int isspace(int ch);</td>
          <td></td>
      </tr>
      <tr>
          <td>int ispunct(int ch);//是否是标点符号</td>
          <td></td>
      </tr>
      <tr>
          <td>int iscntrl(int ch);//是否是 control</td>
          <td></td>
      </tr>
      <tr>
          <td>int isprint(int ch);//是否是可打印字符</td>
          <td></td>
      </tr>
      <tr>
          <td>int isgraph(int ch);//是否图形表示</td>
          <td></td>
      </tr>
  </tbody>
</table>

<h2 id="2-字符串c-string-和-string-类" data-numberify>2. 字符串：C-String 和 string 类<a class="anchor ms-1" href="#2-字符串c-string-和-string-类"></a></h2>
<p>回顾一下，我们知道 C++支持两种类型的字符串：</p>]]></description></item><item><title>c++编程之操作符重载</title><link>https://blog.liubang.cc/posts/cpp/2018-03-14-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%93%8D%E4%BD%9C%E7%AC%A6%E9%87%8D%E8%BD%BD/</link><pubDate>Wed, 14 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-03-14-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%93%8D%E4%BD%9C%E7%AC%A6%E9%87%8D%E8%BD%BD/</guid><description><![CDATA[<p>操作符重载就是指操作符会对不同类型的操作数表现出不同的行为。例如：(a) 按位左移操作符&rsquo;&laquo;&lsquo;在操作流对象的时候就变成了插入操作；(b) <code>*</code>操作符操作于两个数字的时候就是乘法操作，而作用于
地址的时候就是间接寻址操作。C++允许你再用户端扩展操作符重载。</p>
<p>操作符重载就像函数重载那样，同一个函数名可以因为参数不同而同时存在很多版本。</p>

<h2 id="1-string-类中重载的操作符" data-numberify>1. string 类中重载的操作符<a class="anchor ms-1" href="#1-string-类中重载的操作符"></a></h2>
<p>C++的&quot;string&quot;类中重载了以下操作符来作用于&quot;string&quot;对象：</p>
<ul>
<li>字符串比较操作(=,!=,&gt;,&lt;,&gt;=,&lt;=)：例如，使用<code>str1 == str2</code>来比较两个&quot;string&quot;对象</li>
<li>流插入和取出操作(&laquo;,&raquo;)：例如，你可以使用<code>cout &lt;&lt; st1</code>和<code>cin &gt;&gt; str2</code>来输出/输入&quot;string&quot;对象</li>
<li>字符串连接(+,+=)：例如，<code>str1 + str2</code>，将两个&quot;string&quot;对象合并成一个新的&quot;string&quot;对象，<code>str1 += str2</code>将<code>str2</code>追加到<code>str1</code>后</li>
<li>字符索引或下标([])：例如，你可以使用<code>str[n]</code>来获取下标为 n 的字符；或者<code>str[n] = c</code>来修改下标为 n 处的字符。需要注意的是&rsquo;[]&lsquo;操作符不会
做边界检测，也就是说，你需要自己保证下标不会超出边界，你可以使用&quot;string&quot;类的<code>at()</code>函数来做边界检测</li>
<li>赋值(=)：例如，<code>str1 = str2</code>，将<code>str2</code>赋值给<code>str1</code></li>
</ul>
<p>示例代码：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;iostream&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;iomanip&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;string&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#c678dd">using</span> <span style="color:#c678dd">namespace</span> <span style="color:#e06c75">std</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">argv</span>[]) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>	<span style="color:#e06c75">string</span> <span style="color:#e06c75">msg1</span>(<span style="color:#98c379">&#34;hello&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>	<span style="color:#e06c75">string</span> <span style="color:#e06c75">msg2</span>(<span style="color:#98c379">&#34;HELLO&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>	<span style="color:#e06c75">string</span> <span style="color:#e06c75">msg3</span>(<span style="color:#98c379">&#34;hello&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">boolalpha</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> (<span style="color:#e06c75">msg1</span> <span style="color:#56b6c2">==</span> <span style="color:#e06c75">msg2</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> (<span style="color:#e06c75">msg1</span> <span style="color:#56b6c2">==</span> <span style="color:#e06c75">msg3</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> (<span style="color:#e06c75">msg1</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">msg2</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>	<span style="color:#e06c75">string</span> <span style="color:#e06c75">msg4</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">msg1</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">msg4</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> (<span style="color:#e06c75">msg1</span> <span style="color:#56b6c2">+</span> <span style="color:#98c379">&#34; &#34;</span> <span style="color:#56b6c2">+</span> <span style="color:#e06c75">msg2</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>	<span style="color:#e06c75">msg3</span> <span style="color:#56b6c2">+=</span> <span style="color:#e06c75">msg2</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">msg3</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">msg1</span>[<span style="color:#d19a66">1</span>] <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">msg1</span>[<span style="color:#d19a66">99</span>] <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span>	<span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span>}
</span></span></code></pre></div>
<h2 id="2-用户自定义操作符重载" data-numberify>2. 用户自定义操作符重载<a class="anchor ms-1" href="#2-用户自定义操作符重载"></a></h2>

<h3 id="21-operator函数" data-numberify>2.1 “operator"函数<a class="anchor ms-1" href="#21-operator函数"></a></h3>
<p>为了实现操作符重载，我们需要使用一种特殊的函数形式，叫做操作符函数。操作符函数形如：&ldquo;operator Δ()&quot;，Δ 就是将要被重载的操作符。</p>]]></description></item><item><title>c++编程之模板和泛型编程</title><link>https://blog.liubang.cc/posts/cpp/2018-03-14-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%A8%A1%E6%9D%BF%E5%92%8C%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B/</link><pubDate>Wed, 14 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-03-14-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%A8%A1%E6%9D%BF%E5%92%8C%E6%B3%9B%E5%9E%8B%E7%BC%96%E7%A8%8B/</guid><description><![CDATA[<h2 id="1-简介" data-numberify>1. 简介<a class="anchor ms-1" href="#1-简介"></a></h2>
<p>我们对传递数值或变量给函数都很熟悉，除了传递变量，我们还能传递类型给模板。传递类型就是大家所熟知的泛型编程，因为
我们可以用泛型编写程序，而用特定的类型调用。</p>
<p>泛型编程的目的是为了编写的程序不依赖于数据类型。在 C 语言中，所有的代码都需要绑定到确定的数据类型，这样写的代码只能对特定的数据类型起作用。
而模板可以让我们实现泛型编程。你可以将类型作为参数来构建模板函数和类模板。当你的算法需要作用于多种数据类型的时候，模板就显得及其有用了。</p>
<p>C++的标准模板库(STL)提供了一些常用的容器类模板的实现，例如<code>vector</code>，可以用来存放所有类型的元素。</p>

<h2 id="2-示例stl-中的-vector-类模板" data-numberify>2. 示例：STL 中的 vector 类模板<a class="anchor ms-1" href="#2-示例stl-中的-vector-类模板"></a></h2>
<p>C/C++中的内置数组有一些缺点：</p>
<ol>
<li>它的大小是固定的，需要在声明的时候确定大小，不支持动态声明。你不能在执行期给数组扩容；</li>
<li>数组不提供下标边界校验，你可以使用超出边界的下标</li>
<li>你需要自己实现数组比较，和赋值操作</li>
</ol>
<p>C++提供了一个<code>vector</code>类模板，作为标准模板库(STL)的一部分。<code>vector</code>被定义在<code>&lt;vector&gt;</code>头文件中，属于<code>std</code>命名空间。vector 是最常用的 STL 类，它能够取代数组，并且支持动态分配空间和一些其它操作（例如比较和赋值）。</p>
<p>vector 是一个类模板，它可以被特定类型的实例化，形如：<code>vector&lt;int&gt;</code>, <code>vector&lt;double&gt;</code>, <code>vector&lt;string&gt;</code>。同一个模板能够用于多种类型，而不必为每种类型都写一套实现。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;iostream&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;vector&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&lt;string&gt;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span><span style="color:#c678dd">using</span> <span style="color:#c678dd">namespace</span> <span style="color:#e06c75">std</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">print</span>(<span style="color:#c678dd">const</span> <span style="color:#e06c75">vector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span><span style="color:#56b6c2">&gt;</span> <span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">v</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">argc</span>, <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">argv</span>[]) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>	<span style="color:#e06c75">vector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">v1</span>(<span style="color:#d19a66">5</span>); <span style="color:#7f848e">// Create a vector with 5 elements.
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>	<span style="color:#7f848e">// Assign values into v1, using array-like index []
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>	<span style="color:#7f848e">// You can retrieve the size of vector via size()
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>	<span style="color:#c678dd">for</span> (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">v1</span>.<span style="color:#e06c75">size</span>(); <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span>		<span style="color:#e06c75">v1</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">=</span> (<span style="color:#e06c75">i</span> <span style="color:#56b6c2">+</span> <span style="color:#d19a66">1</span>) <span style="color:#56b6c2">*</span> <span style="color:#d19a66">2</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span>	}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-17">17</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-18">18</a></span><span>	<span style="color:#7f848e">// Print vector content, using at()
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-19">19</a></span><span>	<span style="color:#c678dd">for</span> (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">v1</span>.<span style="color:#e06c75">size</span>(); <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-20">20</a></span><span>		<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">v1</span>.<span style="color:#e06c75">at</span>(<span style="color:#e06c75">i</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#34; &#34;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-21">21</a></span><span>	}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-22">22</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-23">23</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-24">24</a></span><span>	<span style="color:#e06c75">vector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e5c07b">int</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">v2</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-25">25</a></span><span>	<span style="color:#7f848e">// Assign v1 to v2 memberwise
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-26">26</a></span><span>	<span style="color:#e06c75">v2</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">v1</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-27"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-27">27</a></span><span>	<span style="color:#c678dd">for</span> (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">v2</span>.<span style="color:#e06c75">size</span>(); <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-28"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-28">28</a></span><span>		<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">v2</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#34; &#34;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-29"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-29">29</a></span><span>	}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-30"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-30">30</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-31"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-31">31</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-32"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-32">32</a></span><span>	<span style="color:#7f848e">// Compare 2 vectors memberwise
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-33"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-33">33</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">boolalpha</span> <span style="color:#56b6c2">&lt;&lt;</span> (<span style="color:#e06c75">v1</span> <span style="color:#56b6c2">==</span> <span style="color:#e06c75">v2</span>) <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-34"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-34">34</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-35"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-35">35</a></span><span>	<span style="color:#7f848e">// Append more elements - synamically allocate memory
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-36"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-36">36</a></span><span>	<span style="color:#e06c75">v1</span>.<span style="color:#e06c75">push_back</span>(<span style="color:#d19a66">80</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-37"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-37">37</a></span><span>	<span style="color:#e06c75">v1</span>.<span style="color:#e06c75">push_back</span>(<span style="color:#d19a66">81</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-38"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-38">38</a></span><span>	<span style="color:#c678dd">for</span> (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">v1</span>.<span style="color:#e06c75">size</span>(); <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-39"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-39">39</a></span><span>		<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">v1</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#34; &#34;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-40"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-40">40</a></span><span>	}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-41"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-41">41</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-42"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-42">42</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-43"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-43">43</a></span><span>	<span style="color:#e06c75">vector</span><span style="color:#56b6c2">&lt;</span><span style="color:#e06c75">string</span><span style="color:#56b6c2">&gt;</span> <span style="color:#e06c75">v3</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-44"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-44">44</a></span><span>	<span style="color:#e06c75">v3</span>.<span style="color:#e06c75">push_back</span>(<span style="color:#98c379">&#34;a for apple&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-45"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-45">45</a></span><span>	<span style="color:#e06c75">v3</span>.<span style="color:#e06c75">push_back</span>(<span style="color:#98c379">&#34;b for boy&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-46"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-46">46</a></span><span>	<span style="color:#c678dd">for</span> (<span style="color:#e5c07b">int</span> <span style="color:#e06c75">i</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>; <span style="color:#e06c75">i</span> <span style="color:#56b6c2">&lt;</span> <span style="color:#e06c75">v3</span>.<span style="color:#e06c75">size</span>(); <span style="color:#e06c75">i</span><span style="color:#56b6c2">++</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-47"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-47">47</a></span><span>		<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">v3</span>[<span style="color:#e06c75">i</span>] <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#98c379">&#34; &#34;</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-48"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-48">48</a></span><span>	}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-49"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-49">49</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-50"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-50">50</a></span><span>	<span style="color:#e06c75">cout</span> <span style="color:#56b6c2">&lt;&lt;</span> <span style="color:#e06c75">endl</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-51"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-51">51</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-52"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-52">52</a></span><span>	<span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-53"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-53">53</a></span><span>}
</span></span></code></pre></div><p>说明：</p>]]></description></item><item><title>c++编程之继承和多态</title><link>https://blog.liubang.cc/posts/cpp/2018-03-05-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BB%A7%E6%89%BF%E5%92%8C%E5%A4%9A%E6%80%81/</link><pubDate>Mon, 05 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-03-05-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E7%BB%A7%E6%89%BF%E5%92%8C%E5%A4%9A%E6%80%81/</guid><description><![CDATA[<h2 id="1-继承" data-numberify>1. 继承<a class="anchor ms-1" href="#1-继承"></a></h2>

<h3 id="11-术语" data-numberify>1.1 术语<a class="anchor ms-1" href="#11-术语"></a></h3>
<p>超类（基类）和子类（派生类）：在面向对象程序设计中，我们通常使用继承来避免代码冗余。在 C++中，继承的语法规则如下：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">SubclassName</span> <span style="color:#56b6c2">:</span> <span style="color:#e06c75">inheritance</span><span style="color:#56b6c2">-</span><span style="color:#e06c75">access</span><span style="color:#56b6c2">-</span><span style="color:#e06c75">specifier</span> <span style="color:#e06c75">SuperclassName</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>	......
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>};
</span></span></code></pre></div><p>子类继承了父类所有的成员，子类也可以定义自己的构造器和成员。</p>
<p><strong>访问标识符</strong>：C++支持三种访问标识符：<code>private</code>，<code>public</code>和<code>protected</code>。一个类的 public 成员变量、成员函数，可以通过类的成员函数、类的实例变量进行访问。
一个类的 protected 成员变量、成员函数，无法通过类的实例变量进行访问。但是可以通过类的友元函数、友元类进行访问。一个类的 private 成员变量、成员函数，无法通过类的实例变量进行访问。但是可以通过类的友元函数、友元类进行访问。</p>
<p><strong>继承访问标识符</strong>：public 继承不改变基类成员的访问权限，private 继承使得基类所有成员在子类中的访问权限变为 private，protected 继承将基类中 public 成员变为子类的 protected 成员，其它成员的访问 权限不变。
基类中的 private 成员不受继承方式的影响，子类永远无权访问。</p>

<h3 id="12-一个示例" data-numberify>1.2 一个示例<a class="anchor ms-1" href="#12-一个示例"></a></h3>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2018-03-05/ClassDiagram_MovablePoint.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="289" height="584" />
</picture>

</p>
<p>MovablePoint.h</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#7f848e">#ifndef MOVING_POINT_H
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span><span style="color:#7f848e">#define MOVING_POINT_H
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span><span style="color:#7f848e">#include</span> <span style="color:#7f848e">&#34;Point.h&#34;</span><span style="color:#7f848e">
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">MoviablePoint</span> <span style="color:#56b6c2">:</span> <span style="color:#c678dd">public</span> <span style="color:#e06c75">Point</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span><span style="color:#c678dd">private</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>	<span style="color:#e5c07b">int</span> <span style="color:#e06c75">xSpeed</span>, <span style="color:#e06c75">ySpeed</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>	<span style="color:#e06c75">MovablePoint</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">x</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">y</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">xSpeed</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">ySpeed</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span>	<span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">getXSpeed</span>() <span style="color:#c678dd">const</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-13">13</a></span><span>	<span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">getYSpeed</span>() <span style="color:#c678dd">const</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-14">14</a></span><span>	<span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">setXSpeed</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">xSpeed</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-15">15</a></span><span>	<span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">setYSpeed</span>(<span style="color:#e5c07b">int</span> <span style="color:#e06c75">ySpeed</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-16">16</a></span><span>	<span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">move</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-17">17</a></span><span>	<span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">print</span>() <span style="color:#c678dd">const</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-18">18</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-19">19</a></span><span><span style="color:#7f848e">#endif
</span></span></span></code></pre></div><p>MovablePoint.cpp</p>]]></description></item><item><title>c++编程之OOP示例</title><link>https://blog.liubang.cc/posts/cpp/2018-03-02-c++%E7%BC%96%E7%A8%8B%E4%B9%8Boop%E7%A4%BA%E4%BE%8B/</link><pubDate>Fri, 02 Mar 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-03-02-c++%E7%BC%96%E7%A8%8B%E4%B9%8Boop%E7%A4%BA%E4%BE%8B/</guid><description><![CDATA[<h2 id="1-示例使用引用的time类" data-numberify>1. 示例：使用引用的"Time"类<a class="anchor ms-1" href="#1-示例使用引用的time类"></a></h2>
<p>回到之前版本的&quot;Time&quot;类，假设我们想增加链式操作，例如<code>t.nextSecond().nextSecond().print()</code>，我们就需要让<code>nextSecond()</code>返回<code>this</code>的一个引用。</p>
<p>Time.h</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">class</span> <span style="color:#e5c07b">Time</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#c678dd">private</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>	......
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span><span style="color:#c678dd">public</span><span style="color:#56b6c2">:</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>	<span style="color:#e06c75">Time</span> <span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">nextSecond</span>(); <span style="color:#7f848e">// Return a reference to &#34;this&#34; instance
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6">6</a></span><span>	......
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7">7</a></span><span>}
</span></span></code></pre></div><p>在函数原型中，我们申明了一个<code>nextSecond()</code>的成员函数，返回<code>Time</code>对象的引用。返回的引用可以用来继续调用成员函数。</p>
<p>Time.cpp</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#7f848e">// Increase this instance by one second and return this instance by reference.
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span><span style="color:#e06c75">Time</span> <span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">Time</span><span style="color:#56b6c2">::</span><span style="color:#e06c75">nextSecond</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>	<span style="color:#c678dd">if</span> (<span style="color:#56b6c2">++</span><span style="color:#e06c75">second</span> <span style="color:#56b6c2">==</span> <span style="color:#d19a66">60</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>		<span style="color:#e06c75">second</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>		<span style="color:#c678dd">if</span> (<span style="color:#56b6c2">++</span><span style="color:#e06c75">minute</span> <span style="color:#56b6c2">==</span> <span style="color:#d19a66">60</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>			<span style="color:#e06c75">minute</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span>			<span style="color:#c678dd">if</span> (<span style="color:#56b6c2">++</span><span style="color:#e06c75">hour</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">24</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>				<span style="color:#e06c75">hour</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>			}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>		}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>	}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-13">13</a></span><span>	<span style="color:#c678dd">return</span> <span style="color:#56b6c2">*</span><span style="color:#c678dd">this</span>; <span style="color:#7f848e">// Return this instance by reference
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-14">14</a></span><span>				  <span style="color:#7f848e">// &#34;this&#34; is a pointer to this instance. *this refers to the instance.
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-15">15</a></span><span>}
</span></span></code></pre></div><p>C++有一个关键字&quot;this&quot;，它保存了一个指向当前实例的指针。也就是说，<code>*this</code>指的是当前实例。</p>]]></description></item><item><title>c++编程之指针，引用和内存动态分配</title><link>https://blog.liubang.cc/posts/cpp/2018-02-23-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%8C%87%E9%92%88%E5%BC%95%E7%94%A8%E5%92%8C%E5%86%85%E5%AD%98%E5%8A%A8%E6%80%81%E5%88%86%E9%85%8D/</link><pubDate>Fri, 23 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-02-23-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E6%8C%87%E9%92%88%E5%BC%95%E7%94%A8%E5%92%8C%E5%86%85%E5%AD%98%E5%8A%A8%E6%80%81%E5%88%86%E9%85%8D/</guid><description><![CDATA[<p>指针，引用和动态分配内存是 C/C++语言中最强大的特性，这些特性使得程序员能够直接操作计算机中非常珍贵的记忆体资源，进而对内存进行最大性能和高效的使用。
然而指针也是一把双刃剑，它也是 C/C++编程语言中最复杂和最难的特性。</p>
<p>指针之所以这么强大，是因为它允许你通过地址来访问和操作对应记忆体中存储的内容。但是指针也很难被驾驭，使用好的话确实能够大大提升性能，而用的
不好的话，也会导致很多问题，例如著名的内存泄漏和缓冲区溢出，这些 bug 会致使系统发生紊乱。一些新的编程语言（例如 Java 和 C#），将指针从它的语法
中去掉，通过提供自动内存管理的方式来避免使用指针导致的许多问题。</p>
<p>虽然你在编写 C/C++代码的时候可以不使用指针，但是在学习 C/C++的时候很难不提及指针。指针也许不是为新手和笨蛋而设计的。</p>

<h2 id="1-指针变量" data-numberify>1. 指针变量<a class="anchor ms-1" href="#1-指针变量"></a></h2>
<p>计算机记忆体位置有一个地址，对应地址处保存数据。记忆体地址通常是一个数字（一般用十六进制表示），这个数字很难被程序员直接使用。通常一个地址位置
的容量是 8-bit（也就是 1-byte），里面可以存储整数，实数，字符或者字符串，这完全取决于程序员如何解析。</p>
<p>为了减轻程序员使用数字地址和解析数据的负担，早期的编程语言（例如 C 语言）中产生了一种新的变量——这种变量是一个被命名了的变量的位置，它可以存储一个特定类型的值。
取代数字地址的是用名字（或者标识符）直接关联到确定的地址上，而且变量类型（如<code>int</code>, <code>double</code>, <code>char</code>）与之关联，从而简化了对数据的解析。</p>
<p>每个内存地址占 8 位（也就是 1 个字节），一个 4 个字节的<code>int</code>值需要 4 个内存位置。一个 32 位的系统通常使用 32 位的地址。同样的，存储这个 32 位的地址也需要 4 个内存位置。</p>
<p>下面的插图形象的描绘了计算机内存地址，内存中数据，变量名，变量类型以及变量值之间的关系。</p>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2018-02-23/MemoryAddressContent.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="661" height="503" />
</picture>

</p>

<h3 id="11-指针变量" data-numberify>1.1 指针变量<a class="anchor ms-1" href="#11-指针变量"></a></h3>
<p>指针变量（简称指针）基本上跟其他变量一样，都可以用来存放数据，但是跟普通变量不同的是，普通变量存储的是数值，而指针存放的是内存地址。</p>

<h3 id="12-申明指针" data-numberify>1.2 申明指针<a class="anchor ms-1" href="#12-申明指针"></a></h3>
<p>指针在使用前必须先申明。申明指针的语法是在指针名前加上一个<code>*</code>符号。指针必须跟类型关联。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-cpp" data-lang="cpp"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e06c75">type</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">ptr</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#7f848e">// or
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span><span style="color:#e06c75">type</span><span style="color:#56b6c2">*</span> <span style="color:#e06c75">ptr</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span><span style="color:#7f848e">// or
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span><span style="color:#e06c75">type</span> <span style="color:#56b6c2">*</span> <span style="color:#e06c75">ptr</span>;
</span></span></code></pre></div><p>例如：</p>]]></description></item><item><title>c++编程之面向对象</title><link>https://blog.liubang.cc/posts/cpp/2018-02-13-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</link><pubDate>Tue, 13 Feb 2018 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/cpp/2018-02-13-c++%E7%BC%96%E7%A8%8B%E4%B9%8B%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</guid><description><![CDATA[<h2 id="1-为什么要使用-oop" data-numberify>1. 为什么要使用 OOP？<a class="anchor ms-1" href="#1-为什么要使用-oop"></a></h2>
<p>假如你想组装一台电脑，你会去硬件商店购买主板、处理器、内存条、硬盘、机箱、电源，然后将它们组装在一起，然后打开电源，电脑就能运行。
你不用考虑主板是 4 重板还是 6 重板，硬盘是什么尺寸，内存是哪里生产的诸如此类的问题。你只需要将这些硬件单元组合在一起，就能期待电脑能够运行。
当然，你需要保证你有正确的接口，比如，如果你的主板只支持 IDE 接口，而你需要购买一个 IDE 的硬盘而不是 SCSI 硬盘，又例如你需要选择一个合适速率的
内存。即便如此，将硬件组件组装成一台机器也没有任何难度。</p>
<p>同样的，一辆车也是由多个部分组装起来的，例如底盘、车门、引擎、车轮、刹车和传动装置。这些组件都是可复用的。比如车轮，就能够被用于很多辆同型号的骑车上。</p>
<p>像电脑和汽车这样的硬件能够用可复用的部分组装起来。那么软件是否也是如此呢？我们是否能够将不同地方的程序片段“组装”起来，然后期待程序能正常运行呢？
答案显然是 no！跟硬件不同的是，很难从软件片段中“组装”一个应用。自从计算机 60 年前问世以来，人们写了大量的程式码。然而，对于每一个新的应用程序，我们都需要
重新造轮子。</p>
<p>为什么要重新造轮子呢？</p>

<h3 id="11-传统的面向过程的编程语言" data-numberify>1.1 传统的面向过程的编程语言<a class="anchor ms-1" href="#11-传统的面向过程的编程语言"></a></h3>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2018-02-13/OOP_CFunction.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="326" height="335" />
</picture>

</p>
<p>传统的面向过程的编程语言（例如 C 和 Pascal）在创建可重用组件方面遇到了一些显著的缺陷：</p>
<ol>
<li>
<p>程序是由函数组织起来的。函数通常是不可重用的，我们很难将一个函数直接拷贝到别的地方去使用，因为函数很有可能引用了头文件，或者全局变量，或者调用了其他函数。
换句话说，函数不能很好的封装成一个独立的可重用单元。</p>
</li>
<li>
<p>面向过程的语言不适合高层抽象来解决现实生活中的问题。例如 c 程序使用&quot;if-else&quot;, &ldquo;for-loop&rdquo;, &ldquo;array&rdquo;, &ldquo;function&rdquo;, &ldquo;pointer&quot;等结构，这些结构很低阶而且很难抽象形如
Customer Relationship Management (CRM) 系统或者电脑足球游戏。</p>
</li>
</ol>
<p>简而言之，传统的面向过程的编程语言将数据结构和算法单元分开了。</p>

<h3 id="12-面向对象的编程语言" data-numberify>1.2 面向对象的编程语言<a class="anchor ms-1" href="#12-面向对象的编程语言"></a></h3>
<p><picture><img class="img-fluid mx-auto d-block" alt="" src="https://blog.liubang.cc/images/2018-02-13/OOP_Objects.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="538" height="351" />
</picture>

</p>
<p>面向对象的编程语言就是被设计来克服这些问题的。</p>
<ol>
<li>
<p>OOP 的基础单元是类。类将静态属性和动态行为封装在一起，同时指定一些公开的接口来供人使用。由于相比于函数，类有很好的封装性，所以很容易重用。换句话说，类将数据和算法结合在了一起。</p>
</li>
<li>
<p>面向对象的编程语言为解决现实问题的高阶抽象提供了保证。面向过程的编程语言迫使人们把注意力放在计算机结构（如：内存，位，字节，数组）上，而不是放在要解决的问题本身。面向对象的编程语言
能够让我们更专注于问题本身，使用程序对象来表示和抽象问题中的各种实体。</p>
</li>
</ol>
<p>举个例子，假设你要写一个足球游戏，很难用面向过程的语言建立模型。但是使用 OOP，可以很容易将现实事物同程序之间建立模型：</p>
<ul>
<li>Player：属性包含 name, number, location 等待，操作有 run, jump, kick-the-ball&hellip;</li>
<li>Ball:</li>
<li>Reference:</li>
<li>Field:</li>
<li>Audience:</li>
<li>Weather:</li>
</ul>
<p>最重要的是，这其中的一些类（例如：Ball 和 Audience）可以在其他程序中复用。</p>]]></description></item><item><title>PHP7虚拟机</title><link>https://blog.liubang.cc/posts/php/2017-11-29-php7%E8%99%9A%E6%8B%9F%E6%9C%BA/</link><pubDate>Wed, 29 Nov 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-11-29-php7%E8%99%9A%E6%8B%9F%E6%9C%BA/</guid><description><![CDATA[<p>原文地址<a href="http://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html" target="_blank" rel="noopener noreferrer">http://nikic.github.io/2017/04/14/PHP-7-Virtual-machine.html<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
<p>写这篇文章的目的是基于 php7，阐述 Zend Virtual Machine 的内部实现。这不是一篇综合描述，我将尽可能地覆盖到所有重要的部分和细节。</p>
<p>本文的描述对象是 php7.2 版本，但是几乎所有的特性都已经应用在了 php7.0/7.1 中了。然而，它们同 php5.x 系列 VM 的不同之处同样也很重要，我会很有耐心的同步描述。</p>
<p>这篇文章主要是从指令的角度来阐述，只有在末尾花了少量篇幅描述了 C 语言实现 VM 的细节。但是在文章开始之前，我想先提供一些实现 VM 的主要代码文件：</p>
<ul>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_vm_def.h" target="_blank" rel="noopener noreferrer">zend_vm_def.h<i class="fas fa-external-link-square-alt ms-1"></i></a>: VM 定义文件</li>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_vm_execute.h" target="_blank" rel="noopener noreferrer">zend_vm_execute.h<i class="fas fa-external-link-square-alt ms-1"></i></a>: 生成的 VM</li>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_vm_gen.php" target="_blank" rel="noopener noreferrer">zend_vm_gen.php<i class="fas fa-external-link-square-alt ms-1"></i></a>: VM 生成脚本</li>
<li><a href="https://github.com/php/php-src/blob/master/Zend/zend_execute.c" target="_blank" rel="noopener noreferrer">zend_execute.c<i class="fas fa-external-link-square-alt ms-1"></i></a>: 大多数直接支持的代码</li>
</ul>

<h2 id="opcodes" data-numberify>Opcodes<a class="anchor ms-1" href="#opcodes"></a></h2>
<p>首先我们来聊聊 opcode。&ldquo;Opcode&quot;是用来表示整个 VM 指令集（包括操作数）的，但是也可能仅仅就是指“真实的”操作码，这些操作码是一个很小的整数用来区分不同的指令类型。其具体的含义需要结合代码的上下文才能清楚。在程式码中，指令通常被称作&quot;oplines&rdquo;。</p>
<p>下面是<code>zend_op</code>的结构</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_op</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>    <span style="color:#c678dd">const</span> <span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">handler</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>    <span style="color:#e06c75">znode_op</span> <span style="color:#e06c75">op1</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>    <span style="color:#e06c75">znode_op</span> <span style="color:#e06c75">op2</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>    <span style="color:#e06c75">znode_op</span> <span style="color:#e06c75">result</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#e5c07b">uint32_t</span> <span style="color:#e06c75">extended_value</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#e5c07b">uint32_t</span> <span style="color:#e06c75">lineno</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">opcode</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">op1_type</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">op2_type</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>    <span style="color:#e06c75">zend_uchar</span> <span style="color:#e06c75">result_type</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>};
</span></span></code></pre></div><p>由此看来，opcodes 本质上就是一个“三地址码”格式的指令。有一个<code>opcode</code>代表指令的类型，有两个输入操作数<code>op1</code>和<code>op2</code>和一个输出操作数<code>result</code>。</p>]]></description></item><item><title>PHP和线程</title><link>https://blog.liubang.cc/posts/php/2017-10-12-php%E5%92%8C%E7%BA%BF%E7%A8%8B/</link><pubDate>Thu, 12 Oct 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-10-12-php%E5%92%8C%E7%BA%BF%E7%A8%8B/</guid><description><![CDATA[<p>原文地址<a href="http://blog.jpauli.tech/2017/01/12/threads-and-php.html" target="_blank" rel="noopener noreferrer">http://blog.jpauli.tech/2017/01/12/threads-and-php.html<i class="fas fa-external-link-square-alt ms-1"></i></a></p>

<h2 id="前言" data-numberify>前言<a class="anchor ms-1" href="#前言"></a></h2>
<p>PHP 和线程，单凭这简短的几个字，就足以写一本书。像往常一样，我们不会这么做，但是会给出一定程度上跟这个话题相关的信息与细节。让我们从一些人在谈论这个话题时通常感到的困惑开始，PHP 不是一种线程语言，
PHP 的内核没有使用线程，而且 PHP 天生也不允许用户层代码通过任何方式使用多线程作为并发机制。</p>
<p>因此 PHP 跟其他一些技术有很大的区别，例如 Java。Java 不仅自身使用了大量的线程，它还允许用户通过编程来是用线程。然而，PHP 不适用线程是有它的原因的。</p>
<p>PHP 内核没有使用线程，主要是为了简化开发。当你读到下一节的时候，你就会了解到线程并不是一个能使任何程序都能更快运行的魔法技术。是不是听起来很像是在推销不是吗？但是我们不是推销，而是谈论技术，而且
我们很清楚我们在说什么。因此 PHP 引擎目前没有使用多线程，也许将来会使用。但是使用多线程在编程上会引发很多问题，例如程序运行结果不是你所期待的等等。主要的困难是跨平坦的多线程编程，其次就是资源共享和
锁的管理，再次就是并不是所有的程序都能够被转化成多线程程序。PHP 的设计主要在 2000 前后，在那个时候，多线程编程并不是很广泛和成熟，PHP 引擎开发工程师决定创造一个完全没有线程的单片机引擎（当然他们也没有
足够的能力去驾驭一个稳定的跨平台的多线程引擎）。</p>
<p>PHP 用户层代码也不允许使用线程，因为那不是 PHP 期待你的代码运行的方式。PHP 是一个&quot;发送并忘记(fire-and-forget)&ldquo;型的语言，你应该尽可能快的处理完请求，然后释放，然后接着处理下一个请求。PHP 被设计作为一种
胶水语言：你不用处理可能使用到线程的复杂任务，而是访问快速而且已经准备好的资源，将它们粘合到一起，然后再返回给用户。通过 PHP，无论什么可能花费比通常时间多的时间的任务，都不能用 PHP 来处理。这就是为什么
在 PHP 中我们通常使用基于消息队列的系统(Gearman, AMQP, ActiveMQ 等等)来异步处理一些耗时任务。正如 Unix 看待事物的方式：“开发小而完备的工具，然后将他们连接在一起”。因此 PHP 的设计不是允许大规模的并行，而是
其他专门的技术&ndash;是用正确的工具来解决特定的问题。</p>

<h2 id="线程的简介" data-numberify>线程的简介<a class="anchor ms-1" href="#线程的简介"></a></h2>
<p>让我们来快速的介绍下线程。注意，我们不会阐述太多细节的东西，对于你想深入了解关于线程的任何细节，都可以在相关书籍和站点上找到。</p>
<p>线程是进程中的轻量的事务处理单元，注意，一个进程可以产生多个线程，一个线程必须有且只能属于一个进程。进程是操作系统中的基本工作处理单元。在多 CPU 的机器上，不同的 CPU 将会平行工作，这样对于计算能力的提升会
有很大的好处。如果进程 A 和 B 都准备被执行，而且两个 CPU（或者两个 CPU 核心）也都有空闲的负载，那么进程 A 和 B 将会同时被执行。因此，计算机将能高效的在一个单位时间内同时进行多个运算，我们称之为“并行”(parallelism)。</p>]]></description></item><item><title>理解c语言中的声明</title><link>https://blog.liubang.cc/posts/sp/2017-09-12-%E7%90%86%E8%A7%A3c%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%A3%B0%E6%98%8E/</link><pubDate>Tue, 12 Sep 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2017-09-12-%E7%90%86%E8%A7%A3c%E8%AF%AD%E8%A8%80%E4%B8%AD%E7%9A%84%E5%A3%B0%E6%98%8E/</guid><description><![CDATA[<p>在阅读优秀的 c 语言开源程式的时候，我们经常会看到各种复杂的声明，顿时会让我们怀疑人生，怀疑自己是否真的看得懂 c 语言。然而冷静三秒钟，透过现象看本质，发现牛人写的代码并不是“天书”，
也是很好懂的，关键是要冷静和耐心去阅读。</p>

<h2 id="从中的一个例子说起" data-numberify>从“中的一个例子说起<a class="anchor ms-1" href="#从中的一个例子说起"></a></h2>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span>(<span style="color:#56b6c2">*</span>(<span style="color:#e5c07b">void</span>(<span style="color:#56b6c2">*</span>)())<span style="color:#d19a66">0</span>)()
</span></span></code></pre></div><p>下面我们来一步步分析：</p>
<p>我们知道变量的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#e06c75">a</span>;
</span></span></code></pre></div><p>函数的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-2-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-2-1">1</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">fn</span>();
</span></span></code></pre></div><p>指针的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-3-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-3-1">1</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#d19a66">10</span>;
</span></span></code></pre></div><p>函数指针的声明方式为：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-4-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-4-1">1</a></span><span><span style="color:#e5c07b">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">fn</span>)(); <span style="color:#7f848e">//fn 是一个指向返回int型的函数的指针
</span></span></span></code></pre></div><p>函数指针的调用方式：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-1"> 1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#61afef;font-weight:bold">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">fn_type</span>)();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-2"> 2</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-3"> 3</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">fn</span>() {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-4"> 4</a></span><span>    <span style="color:#c678dd">return</span> <span style="color:#d19a66">0</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-5"> 5</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-7"> 7</a></span><span><span style="color:#e06c75">fn_type</span> <span style="color:#e06c75">a</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">fn</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-8"> 8</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-9"> 9</a></span><span><span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;%d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, <span style="color:#61afef;font-weight:bold">a</span>());
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-10">10</a></span><span><span style="color:#7f848e">//或者
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-5-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-5-11">11</a></span><span><span style="color:#61afef;font-weight:bold">printf</span>(<span style="color:#98c379">&#34;%d</span><span style="color:#98c379">\n</span><span style="color:#98c379">&#34;</span>, (<span style="color:#56b6c2">*</span>)<span style="color:#61afef;font-weight:bold">a</span>());
</span></span></code></pre></div><p>最简单的类型转换：</p>]]></description></item><item><title>PHP扩展开发之迭代器</title><link>https://blog.liubang.cc/posts/php/2017-08-28-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%BF%AD%E4%BB%A3%E5%99%A8/</link><pubDate>Mon, 28 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-28-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%BF%AD%E4%BB%A3%E5%99%A8/</guid><description><![CDATA[<h2 id="preface" data-numberify>preface<a class="anchor ms-1" href="#preface"></a></h2>
<p>在之前的文章中，我们已经实现了一些 object handlers 来将我们的 ArrayBuffer 整合到 php 中。但是美中不足的是，我们的 ArrayBufferView 并不支持迭代器操作。也就是它不能像 php 中的数组那样使用<code>foreach</code>来遍历。
那么，我们接下来就来看看迭代器在内核中是如何实现的，并且给我们的 ArrayBufferView 也增加一个迭代器。</p>

<h2 id="get_iterator-handler" data-numberify>get_iterator handler<a class="anchor ms-1" href="#get_iterator-handler"></a></h2>
<p>内核中的迭代器跟用户端的<code>IteratorAggregate</code>接口功能是一样的。一个具有迭代功能的类都有一个<code>get_iterator</code>处理器，它会返回一个<code>zend_object_iterator *</code>类型的结构，该结构定义如下（位于 phpsrc/Zend/zend_iterators.h 中）：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_object_iterator</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">data</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e06c75">zend_object_iterator_funcs</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">funcs</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#e06c75">ulong</span> <span style="color:#e06c75">index</span>; <span style="color:#7f848e">/* private to fe_reset/fe_fetch opcodes */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>};
</span></span></code></pre></div><p>其中的<code>index</code>成员就是内核中用以实现<code>foreach</code>的，它的值会在每次迭代后增加。<code>funcs</code>成员包含了不同的迭代操作：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_object_iterator_funcs</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>    <span style="color:#7f848e">/* release all resources associated with this iterator instance */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">dtor</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>    <span style="color:#7f848e">/* check for end of iteration (FAILURE or SUCCESS if data is valid) */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>    <span style="color:#e5c07b">int</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">valid</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>    <span style="color:#7f848e">/* fetch the item data for the current element */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">get_current_data</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">***</span><span style="color:#e06c75">data</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>    <span style="color:#7f848e">/* fetch the key for the current element (optional, may be NULL). The key
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span><span style="color:#7f848e">     * should be written into the provided zval* using the ZVAL_* macros. If
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-13">13</a></span><span><span style="color:#7f848e">     * this handler is not provided auto-incrementing integer keys will be
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-14">14</a></span><span><span style="color:#7f848e">     * used. */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-15">15</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">get_current_key</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-16">16</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-17">17</a></span><span>    <span style="color:#7f848e">/* step forwards to next element */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-18">18</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">move_forward</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-19">19</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-20">20</a></span><span>    <span style="color:#7f848e">/* rewind to start of data (optional, may be NULL) */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-21">21</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">rewind</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-22">22</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-23">23</a></span><span>    <span style="color:#7f848e">/* invalidate current value/key (optional, may be NULL) */</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-24">24</a></span><span>    <span style="color:#e5c07b">void</span> (<span style="color:#56b6c2">*</span><span style="color:#e06c75">invalidate_current</span>)(<span style="color:#e06c75">zend_object_iterator</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">iter</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-25">25</a></span><span>} <span style="color:#e06c75">zend_object_iterator_funcs</span>;
</span></span></code></pre></div><p>这些处理器跟<code>Iterator</code>接口中的抽象方法类似，只不过名字不同罢了。唯一没有对应用户端接口的是<code>invalidate_current</code>，它可以被用来销毁当前的<code>key/value</code>。
然而这个操作几乎不会被用到，通常<code>foreach</code>也不会取调用它。</p>]]></description></item><item><title>PHP扩展开发之对象处理器(Object Handlers)</title><link>https://blog.liubang.cc/posts/php/2017-08-27-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E5%AF%B9%E8%B1%A1%E5%A4%84%E7%90%86%E5%99%A8/</link><pubDate>Sun, 27 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-27-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E5%AF%B9%E8%B1%A1%E5%A4%84%E7%90%86%E5%99%A8/</guid><description><![CDATA[<h2 id="object-handlers" data-numberify>Object Handlers<a class="anchor ms-1" href="#object-handlers"></a></h2>
<p>在前面的博文中，已经介绍过一些 object handlers 了，也特别介绍了如何通过指定 handlers 来创建一个自定义的结构和使用<code>clone_obj</code>来对自定义的结构进行克隆操作。
然而，这只是开始：在 php 中，几乎所有的对象操作，都可以通过 object handlers 来实现，而且所有的魔术方法和魔术接口在内核中都是实现了对应的 object handler。此外，
一些 handlers 并没有开放给用户端的 php，例如，内部类可以自定义类的比较操作，而使用 php 代码是无法实现的。</p>
<p>由于 php 中有很多不同的 object handlers，这里只挑几个来讨论，其它的只给出简单的说明。</p>

<h2 id="概述" data-numberify>概述<a class="anchor ms-1" href="#概述"></a></h2>
<p>下面列举出 php 中主要的 26 个(php5.6 中为 28 个)object handlers（位于 phpsrc/Zend/zend_object_handlers.h），并给出简要的说明。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">read_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">type</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">write_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">value</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">has_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">has_set_exists</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">unset_property</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#61afef;font-weight:bold">get_property_ptr_ptr</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#c678dd">const</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_literal</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">key</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span></code></pre></div><p>上述 handlers 分别表示<code>__get</code>，<code>__set</code>，<code>__isset</code>，<code>__unset</code>方法。<code>get_property_ptr_ptr</code>等同于<code>__get</code>返回一个引用类型。<code>zend_literal *key</code>作为这些函数的参数
起到优化作用，例如它包含了一些将属性名进行 hash 计算的结果。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">read_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">offset</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">type</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">write_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">offset</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">value</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span><span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">has_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">member</span>, <span style="color:#e5c07b">int</span> <span style="color:#e06c75">check_empty</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">unset_dimension</span>(<span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">offset</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span></code></pre></div><p>上述了几个 handlers 就是内核用以实现<code>ArrayAccess</code>接口的。</p>]]></description></item><item><title>PHP扩展开发之打造一个简易的ArrayBuffer</title><link>https://blog.liubang.cc/posts/php/2017-08-25-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E6%89%93%E9%80%A0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84arraybuffer/</link><pubDate>Fri, 25 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-25-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E6%89%93%E9%80%A0%E4%B8%80%E4%B8%AA%E7%AE%80%E6%98%93%E7%9A%84arraybuffer/</guid><description><![CDATA[<h2 id="arraybuffer-简介" data-numberify>ArrayBuffer 简介<a class="anchor ms-1" href="#arraybuffer-简介"></a></h2>
<p>ArrayBuffer 又叫二进制数组，是一个用来表示通用的，固定长度的二进制数据缓冲区。你不能直接操纵 ArrayBuffer 的内容，
而是创建一个表示特定格式的 buffer 的类型化数组对象（也叫做数据视图对象）来对 buffer 的内容进行读写操作。</p>
<p>我最早了解 ArrayBuffer 是从 JavaScript 开始的，具体的用法和 api 可以参考<a href="https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer" target="_blank" rel="noopener noreferrer">JavaScript 标准库－－ArrayBuffer<i class="fas fa-external-link-square-alt ms-1"></i></a></p>
<p>那么接下来，我们就给 PHP 扩展一个简单的 ArrayBuffer，顺便巩固一下<a href="https://iliubang.github.io/c/2017/08/24/php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AD%98%E5%82%A8/" target="_blank" rel="noopener noreferrer">php 扩展开发之自定义对象的存储<i class="fas fa-external-link-square-alt ms-1"></i></a>。</p>

<h2 id="定义-arraybuffer-的数据结构和相关-handlers" data-numberify>定义 ArrayBuffer 的数据结构和相关 handlers<a class="anchor ms-1" href="#定义-arraybuffer-的数据结构和相关-handlers"></a></h2>
<p><code>ArrayBuffer</code>是一个非常简单的对象，它只需要申明并存储一个<code>buffer</code>和它的长度即可：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_buffer_object</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#e06c75">zend_object</span> <span style="color:#e06c75">std</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">buffer</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>    <span style="color:#e5c07b">size_t</span> <span style="color:#e06c75">length</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5">5</a></span><span>} <span style="color:#e06c75">buffer_object</span>;
</span></span></code></pre></div><p>接下来我们来实现它的<code>create</code>和<code>free</code> handlers，有了前面的基础，这个实现也是及其简单的：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">static</span> <span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">linger_array_buffer_free_object_storage</span>(<span style="color:#e06c75">buffer_object</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">intern</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>	<span style="color:#61afef;font-weight:bold">zend_object_std_dtor</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">std</span> <span style="color:#e06c75">TSRMLS_CC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>	<span style="color:#61afef;font-weight:bold">linger_efree</span>(<span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">buffer</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span><span style="color:#e06c75">zend_object_value</span> <span style="color:#61afef;font-weight:bold">linger_array_buffer_create_object</span>(<span style="color:#e06c75">zend_class_entry</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">class_type</span> <span style="color:#e06c75">TSRMLS_DC</span>)
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>{
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>	<span style="color:#e06c75">zend_object_value</span> <span style="color:#e06c75">retval</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>	<span style="color:#e06c75">buffer_object</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">intern</span> <span style="color:#56b6c2">=</span> <span style="color:#61afef;font-weight:bold">emalloc</span>(<span style="color:#c678dd">sizeof</span>(<span style="color:#e06c75">buffer_object</span>));
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>	<span style="color:#61afef;font-weight:bold">memset</span>(<span style="color:#e06c75">intern</span>, <span style="color:#d19a66">0</span>, <span style="color:#c678dd">sizeof</span>(<span style="color:#e06c75">buffer_object</span>));
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-12">12</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-13">13</a></span><span>	<span style="color:#61afef;font-weight:bold">zend_object_std_init</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">std</span>, <span style="color:#e06c75">class_type</span> <span style="color:#e06c75">TSRMLS_CC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-14">14</a></span><span>	<span style="color:#61afef;font-weight:bold">object_properties_init</span>(<span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">intern</span><span style="color:#56b6c2">-&gt;</span><span style="color:#e06c75">std</span>, <span style="color:#e06c75">class_type</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-15">15</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-16">16</a></span><span>	<span style="color:#e06c75">retval</span>.<span style="color:#e06c75">handle</span> <span style="color:#56b6c2">=</span> <span style="color:#61afef;font-weight:bold">zend_objects_store_put</span>(
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-17"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-17">17</a></span><span>			<span style="color:#e06c75">intern</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-18"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-18">18</a></span><span>			(<span style="color:#e5c07b">zend_objects_store_dtor_t</span>) <span style="color:#e06c75">zend_objects_destroy_object</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-19"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-19">19</a></span><span>			(<span style="color:#e5c07b">zend_objects_free_object_storage_t</span>) <span style="color:#e06c75">linger_array_buffer_free_object_storage</span>,
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-20"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-20">20</a></span><span>			<span style="color:#e5c07b">NULL</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-21"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-21">21</a></span><span>			<span style="color:#e06c75">TSRMLS_CC</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-22"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-22">22</a></span><span>			);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-23"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-23">23</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-24"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-24">24</a></span><span>	<span style="color:#e06c75">retval</span>.<span style="color:#e06c75">handlers</span> <span style="color:#56b6c2">=</span> <span style="color:#56b6c2">&amp;</span><span style="color:#e06c75">linger_array_buffer_handlers</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-25"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-25">25</a></span><span>	<span style="color:#c678dd">return</span> <span style="color:#e06c75">retval</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-26"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-26">26</a></span><span>}
</span></span></code></pre></div><p>从上面的代码中可以看到，我们并没有在<code>create_object</code>中申请<code>buffer</code>的空间，而这步操作将会在<code>__construct</code>中来实现，因为<code>buffer</code>的长度会作为构造函数的参数传递过来。</p>]]></description></item><item><title>PHP扩展开发之自定义对象的存储</title><link>https://blog.liubang.cc/posts/php/2017-08-24-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AD%98%E5%82%A8/</link><pubDate>Thu, 24 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-08-24-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8B%E8%87%AA%E5%AE%9A%E4%B9%89%E5%AF%B9%E8%B1%A1%E7%9A%84%E5%AD%98%E5%82%A8/</guid><description><![CDATA[<h2 id="前言" data-numberify>前言<a class="anchor ms-1" href="#前言"></a></h2>
<p>对于 php 扩展开发，很多人可能已经不那么陌生了，zend 引擎为了们提供了非常丰富了函数和 macro，来帮助我们很快速的创建一个标准的 php 类，然而，当我们在使用自定义的数据结构(struct)，
并想把我们自己定义的数据结构封装成 php 的类的时候可能就会有些困惑，因为我们都知道 php 中的所有变量都是通过 zval 来存储的，而我们自定义的数据结构要怎样才能和 zval 实现完美的对接呢？
以前我通常采用的一种方式就是使用 zend 引擎提供的资源类型，因为资源类型的封装中包含了通用的数据类型，而且有很丰富的函数来操作资源，所以使用起来很简单也很方便。然而，强大的 zend
引擎真的没有其他方式扩展数据结构了吗？当然不是！下面就来介绍一个更加优雅的方式。要弄明白，首要要搞清 php 内核是如何创建对象的。</p>

<h2 id="如何创建一个对象" data-numberify>如何创建一个对象<a class="anchor ms-1" href="#如何创建一个对象"></a></h2>
<p>我们首先来探讨下如何创建一个 PHP 对象。为此我们将会用到<code>object_and_properties_init</code>之类的一些宏。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#7f848e">// 创建一个SomeClass类型的对象，并且把properties_hashtable中的变量作为其属性值
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span><span style="color:#61afef;font-weight:bold">MAKE_STD_ZVAL</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span><span style="color:#61afef;font-weight:bold">object_and_properties_init</span>(<span style="color:#e06c75">obj</span>, <span style="color:#e06c75">class_entry_of_SomeClass</span>, <span style="color:#e06c75">properties_hashtable</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span><span style="color:#7f848e">// 创建一个没有属性的对象
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span><span style="color:#61afef;font-weight:bold">MAKE_STD_ZVAL</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span><span style="color:#61afef;font-weight:bold">object_init_ex</span>(<span style="color:#e06c75">obj</span>, <span style="color:#e06c75">class_entry_of_SomeClass</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span><span style="color:#7f848e">// = object_and_properties_init(obj, class_entry_of_SomeClass, NULL)
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span><span style="color:#7f848e">// 创建一个stdClass的对象
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span><span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">obj</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span><span style="color:#61afef;font-weight:bold">MAKE_STD_ZVAL</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-15"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-15">15</a></span><span><span style="color:#61afef;font-weight:bold">object_init</span>(<span style="color:#e06c75">obj</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-16"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-16">16</a></span><span><span style="color:#7f848e">// = object_init_ex(obj, NULL) = object_and_properties_init(obj, NULL, NULL);
</span></span></span></code></pre></div><p>在上面的例子中，最后一种情况下，当你创建一个<code>stdClass</code>的对象后，通常将会给它添加属性。这时如果使用
<code>zend_update_property</code>之类的函数，是不起作用的，取而代之的是<code>add_property</code>宏函数：</p>]]></description></item><item><title>数据结构之hashtable</title><link>https://blog.liubang.cc/posts/ds/2017-08-22-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B9%8Bhashtable/</link><pubDate>Tue, 22 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/ds/2017-08-22-%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%E4%B9%8Bhashtable/</guid><description><![CDATA[<h2 id="hashtable" data-numberify>hashtable<a class="anchor ms-1" href="#hashtable"></a></h2>
<p>哈希表又叫散列表，是实现字典操作的中有效数据结构。通常来说，一个 hash table 包含了一个数据，其中的数据通过 index 来访问。
而 hash table 的基本原理就是通过 hash 函数建立起所有可能的 index 与其对应的位置的联系。一个 hash 函数接收一个 key，返回其 hash code，
key 的类型是可变的，而 hash code 是一个整型。</p>
<p>由于计算一个 hash 值和通过 index 访问一个数据都是常量级的时间复杂度，所以我们可以通过这中特性实现常量级时间复杂度的查找。
如果一个 hash 函数能够保证不会有两个不同的 key 生成相同的 hash 值，那么这样的 hash table 就被称为是直接定址。然而，这只是一想法而已，
实际上这种 hash table 在现实中却是不常用的。</p>

<h3 id="chained-hash-table" data-numberify>Chained Hash Table<a class="anchor ms-1" href="#chained-hash-table"></a></h3>
<p>链式 hash 表从本质上来讲，就是一个存放了一组链表的数组。每个链表可以看做是一个槽，我们把元素通过 hash 函数找到一个 hash 值，然后把元素的值
放入到数组中与改 hash 值对应的槽中。</p>
<p><picture><img class="img-fluid mx-auto d-block" alt="chained hashtable" src="https://blog.liubang.cc/images/2017-08-23/chained_hashtable.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="320" height="267" />
</picture>

</p>

<h4 id="collision-resolution" data-numberify>Collision Resolution<a class="anchor ms-1" href="#collision-resolution"></a></h4>
<p>当有两个 key 被 hash 到了同一个位置，就会产生冲突。链式 hash 表有一种简单的冲突解决办法：当冲突产生时，元素被简单的放在同一个槽里。这样做可能带来的问题就是，
如果在同一个位置上出现很多冲突，这个槽就会变得越来越长，这样当我们访问这个槽中的元素的时候，所花的时间也就会越来越长。</p>]]></description></item><item><title>c语言之struct</title><link>https://blog.liubang.cc/posts/sp/2017-08-21-c%E8%AF%AD%E8%A8%80%E4%B9%8Bstruct/</link><pubDate>Mon, 21 Aug 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2017-08-21-c%E8%AF%AD%E8%A8%80%E4%B9%8Bstruct/</guid><description><![CDATA[<h2 id="struct" data-numberify>struct<a class="anchor ms-1" href="#struct"></a></h2>
<blockquote>
<p>在 c 语言中，结构体(struct)是一种复合数据类型，用来将一系列相同或不同类型的变量聚集在同一个内存区间内并赋予同一个名字，使得通过一个指针就能访问集合中的所有成员。结构体中可以包含许多简单或符合数据类型，因此从内存分配上看，有点类似数组，而从变量组织上看，又类似于面向对象编程语言中的类。</p>
</blockquote>

<h3 id="定义-struct" data-numberify>定义 struct<a class="anchor ms-1" href="#定义-struct"></a></h3>
<p>定义一个 struct 非常简单，使用<code>struct</code>关键字即可。</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#c678dd">struct</span> <span style="color:#e06c75">student</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span>    <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">name</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span>    <span style="color:#e5c07b">int</span> <span style="color:#e06c75">age</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4">4</a></span><span>};
</span></span></code></pre></div>
<h3 id="struct-的初始化" data-numberify>struct 的初始化<a class="anchor ms-1" href="#struct-的初始化"></a></h3>
<p>通常有四种常用的 struct 初始化方式。</p>
<p>１．定义并初始化</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1">1</a></span><span><span style="color:#c678dd">struct</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2">2</a></span><span>    <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">ext</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3">3</a></span><span>    <span style="color:#e5c07b">char</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">filetype</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4">4</a></span><span>} <span style="color:#e06c75">extensions</span>[] <span style="color:#56b6c2">=</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5">5</a></span><span>    {<span style="color:#98c379">&#34;gif&#34;</span>, <span style="color:#98c379">&#34;image/gif&#34;</span>},
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6">6</a></span><span>    {<span style="color:#98c379">&#34;jpg&#34;</span>, <span style="color:#98c379">&#34;image/jpg&#34;</span>}
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7">7</a></span><span>};
</span></span></code></pre></div><p>２．按照成员声明的顺序初始化</p>]]></description></item><item><title>Java Native Interface（三）</title><link>https://blog.liubang.cc/posts/java/2017-03-20-java_native_interface%E4%B8%89/</link><pubDate>Mon, 20 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/java/2017-03-20-java_native_interface%E4%B8%89/</guid><description><![CDATA[<p>前面系统研究了 JNI 的相关操作，下面就来小试牛刀，做一个实际的练习。</p>
<p>记得去年我曾经用 C 语言写过一个 PHP 的 md5 扩展函数，那么今天就花一点点时间用 JNI 来实现一遍吧。</p>
<p>不过这里可要提前声明了，虽然是实现 md5 函数，但是这里并不会从头写 md5 算法，而是投机取巧使用到了 linux 内核提供的<code>crypto</code>库。</p>
<p>废话不多说，首先来写一个 Java 类</p>
<p>MyString.java</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#c678dd">public</span> <span style="color:#c678dd">class</span> <span style="color:#e5c07b">MyString</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>    <span style="color:#c678dd">static</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>        <span style="color:#e06c75">System</span>.<span style="color:#e06c75">loadLibrary</span>(<span style="color:#98c379">&#34;mymd5&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#c678dd">private</span> <span style="color:#e06c75">String</span> <span style="color:#e06c75">value</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>    <span style="color:#c678dd">public</span> <span style="color:#c678dd">native</span> <span style="color:#e06c75">String</span> <span style="color:#61afef;font-weight:bold">md5</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#c678dd">public</span> <span style="color:#61afef;font-weight:bold">MyString</span>(<span style="color:#e06c75">String</span> <span style="color:#e06c75">value</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>        <span style="color:#c678dd">this</span>.<span style="color:#e06c75">value</span> <span style="color:#56b6c2">=</span> <span style="color:#e06c75">value</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>}
</span></span></code></pre></div><p>然后生成头文件，并实现 c 代码：</p>]]></description></item><item><title>Java Native Interface（二）</title><link>https://blog.liubang.cc/posts/java/2017-03-20-java_native_interface%E4%BA%8C/</link><pubDate>Mon, 20 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/java/2017-03-20-java_native_interface%E4%BA%8C/</guid><description><![CDATA[<h2 id="1jni-基础" data-numberify>1、JNI 基础<a class="anchor ms-1" href="#1jni-基础"></a></h2>
<p>JNI 中定义了一下类型来对应到相应的 Java 的数据类型:</p>
<p><strong>1. Java 基本数据类型:</strong> <code>jint</code>,<code>jbyte</code>,<code>jshort</code>,<code>jlong</code>,<code>jfloat</code>,<code>jdouble</code>,<code>jchar</code>,<code>jboolean</code>分别对应 Java 中的<code>int</code>,<code>byte</code>,<code>short</code>,<code>long</code>,<code>float</code>,<code>double</code>,<code>char</code>和<code>boolean</code>。</p>
<p><strong>2. Java 引用类型：</strong>
<code>jobject</code>对应<code>java.lang.object</code>。同时也定义了下列子类型：</p>
<ul>
<li><code>jclass</code>对应<code>java.lang.Class</code></li>
<li><code>jstring</code>对应<code>java.lang.String</code></li>
<li><code>jthrowable</code>对应<code>java.lang.Throwable</code></li>
<li><code>jarray</code>对应 Java 中的数组。Java 中的数组由 8 种基本数据类型和一个<code>Object</code>类型派生二来，所以 JNI 中也存在<code>jintArray</code>,<code>jbyteArray</code>,<code>jshortArray</code>,<code>jlongArray</code>,<code>jfloatArray</code>,<code>jdoubleArray</code>,
<code>jcharArray</code>,<code>jbooleanArray</code>和<code>jobjectArray</code></li>
</ul>
<p>native 函数接收和返回上述的 JNI 类型数据。如果 native 函数需要操作它自己的数据类型(如 c 语言中的 int, char *)，那么就需要在 JNI 类型和本地类型之间做相应的转换。</p>
<p>简而言之，native 函数的编写流程大致为：</p>
<ol>
<li>通过 Java 程序接收 JNI 类型的参数</li>
<li>将接收的 JNI 类型转换成本地类型</li>
<li>完成相应的操作</li>
<li>创建一个需要返回的 JNI 类型的对象，然后将返回的数据 copy 到要返回的对象中</li>
<li>返回</li>
</ol>
<p>从上述流程可以看出，编写 JNI 程序主要的挑战在于数据类型之间的转换，然而 JNI 中提供了很多转换函数来帮助我们完成相应的操作。</p>
<p>JNI 是一个 c 语言的接口，c 语言并不支持 OOP 的特性(严格的说，OOP 是一种理念，这里只是从语言本身来说 c 语言不支持面向对象，实际上用 c 语言也可以写出面向对象风格的程序！)，所以他们之间并不是真的通过对象来传递。</p>]]></description></item><item><title>Java Native Interface（一）</title><link>https://blog.liubang.cc/posts/java/2017-03-17-java_native_interface%E4%B8%80/</link><pubDate>Fri, 17 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/java/2017-03-17-java_native_interface%E4%B8%80/</guid><description><![CDATA[<p>最近在整理学习笔记的时候发现了去年年中记录的 JNI 学习笔记，由于存放在了为知笔记中，而如今为知笔记已经不再免费，于是想到了将其重新整理一遍，一来可以巩固所学，二来能将其迁移到本地</p>

<h2 id="1-简介" data-numberify>1 简介<a class="anchor ms-1" href="#1-简介"></a></h2>
<p>有时候，使用 native code(c/c++)来克服 Java 中的内存管理和性能的局限性是很有必要的。Java 支持 native codes，被称作 Java Native Interface(JNI)。</p>
<p>JNI 非常难，毕竟它牵涉到了两种编程语言。假设聪明的你对 Java 和 C/C++以及 GCC 编译器已经有所了解。那么下面就一起来一步步学习 JNI 吧。</p>

<h2 id="2-开始" data-numberify>2 开始<a class="anchor ms-1" href="#2-开始"></a></h2>

<h3 id="21-用-c-语言实现第一个-jni-程序" data-numberify>2.1 用 c 语言实现第一个 JNI 程序<a class="anchor ms-1" href="#21-用-c-语言实现第一个-jni-程序"></a></h3>
<p><strong>Step1:</strong> 创建一个名字为 JNITest.java 的文件</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-java" data-lang="java"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1"> 1</a></span><span><span style="color:#c678dd">public</span> <span style="color:#c678dd">class</span> <span style="color:#e5c07b">JNITest</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2"> 2</a></span><span>    <span style="color:#c678dd">static</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3"> 3</a></span><span>        <span style="color:#e06c75">System</span>.<span style="color:#e06c75">load</span>(<span style="color:#98c379">&#34;/home/ubuntu/workspace/java/jni/mynativelib.so&#34;</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-4"> 4</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-5"> 5</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-6"> 6</a></span><span>    <span style="color:#7f848e">//申明一个无参的native方法，而且返回空</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-7"> 7</a></span><span>    <span style="color:#c678dd">public</span> <span style="color:#c678dd">native</span> <span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">greet</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-8"> 8</a></span><span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-9"> 9</a></span><span>    <span style="color:#7f848e">//测试</span>
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-10">10</a></span><span>    <span style="color:#c678dd">public</span> <span style="color:#c678dd">static</span> <span style="color:#e5c07b">void</span> <span style="color:#61afef;font-weight:bold">main</span>(<span style="color:#e06c75">String</span><span style="color:#56b6c2">[]</span> <span style="color:#e06c75">args</span>) {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-11">11</a></span><span>        <span style="color:#e06c75">JNITest</span> <span style="color:#e06c75">test</span> <span style="color:#56b6c2">=</span> <span style="color:#c678dd">new</span> <span style="color:#e06c75">JNITest</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-12"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-12">12</a></span><span>        <span style="color:#e06c75">test</span>.<span style="color:#e06c75">greet</span>();
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-13"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-13">13</a></span><span>    }
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-14"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-14">14</a></span><span>}
</span></span></code></pre></div><p>首先用静态代码块加载本地动态链接库&quot;mynativelib.so&quot;。对于静态代码块，我相信写过 Java 的你应该非常清楚，它只会在类被加载的时候执行一次。这个动态链接库会被添加到 Java 的 library path（保存在 Java 系统变量 java.library.path）中，如果加载失败，就会抛出<code>UnsatisfiedLinkError</code>异常。也可以使用 JVM 启动参数来加载该动态链接库到 Java 的 library path 当中：</p>]]></description></item><item><title>彻底掌握malloc</title><link>https://blog.liubang.cc/posts/sp/2017-03-17-%E5%BD%BB%E5%BA%95%E6%8E%8C%E6%8F%A1malloc/</link><pubDate>Fri, 17 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/sp/2017-03-17-%E5%BD%BB%E5%BA%95%E6%8E%8C%E6%8F%A1malloc/</guid><description><![CDATA[<p>说明：参考文献地址 <a href="http://www.inf.udec.cl/~leo/Malloc_tutorial.pdf" target="_blank" rel="noopener noreferrer">A Malloc Tutorial<i class="fas fa-external-link-square-alt ms-1"></i></a></p>

<h2 id="1-简介" data-numberify>1 简介<a class="anchor ms-1" href="#1-简介"></a></h2>
<p><code>malloc</code>是干什么的？如果你连这个名字都没听过，那么你应该先去了解 Unix 环境下的 c 语言开发，然后再来阅读。对一个程序员而言，<code>malloc</code>是一个在 c 语言中用来分配内存的函数，但是大多数人并不知道它背后真正的原理，甚至有些人认为<code>malloc</code>是 c 语言的关键字或者认为它是系统调用。事实上，<code>malloc</code>是一个再简单不过的函数而已，而且只需要很少的操作系统相关知识就可以让我们彻底理解它的原理。</p>
<p>下面来一步步的实现一个简单的<code>malloc</code>函数，从而帮助我们理解其背后运作的原理。因为仅仅作为说明原理之用，所以这里实现的<code>malloc</code>不会太高效，但是足以说明原理。</p>
<p>什么是 malloc</p>
<p><code>malloc(3)</code>是一个用来分配内存块的标准的 c 语言库函数。它遵循以下规则：</p>
<ul>
<li><code>malloc</code>至少分配所需字节数的内存；</li>
<li><code>malloc</code>返回其所分配内存空间(程序可以成功读写的空间)的指针；</li>
<li>一块内存一旦被<code>malloc</code>分配，其他<code>malloc</code>调用不能再分配该内存块的任何部分，除非指向该内存块的指针被释放掉；</li>
<li><code>malloc</code>应该是可控的：他必须能够很快完成分配并返回；</li>
<li><code>malloc</code>同时应该提供重新分配内存块大小和释放内存的功能</li>
</ul>
<p><code>malloc</code>函数必须遵循以下原型：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e5c07b">void</span> <span style="color:#56b6c2">*</span><span style="color:#61afef;font-weight:bold">malloc</span>(<span style="color:#e5c07b">size_t</span> <span style="color:#e06c75">size</span>);
</span></span></code></pre></div><p>其中<code>size</code>是所需要的内存大小。如果失败（没有足够的内存空间可以分配），应该返回<code>NULL</code>。</p>

<h2 id="2-堆brk-和-sbrk-系统调用" data-numberify>2 堆，brk 和 sbrk 系统调用<a class="anchor ms-1" href="#2-堆brk-和-sbrk-系统调用"></a></h2>
<p>在开始实现第一个<code>malloc</code>函数之前，需要了解内存在大多数多任务操作系统中是如何管理的。这里我们只是做出一个抽象的解释，从大体上去帮助理解，至于很多细节，它们都依赖操作系统原理和硬件相关的知识。</p>

<h3 id="21-进程的内存" data-numberify>2.1 进程的内存<a class="anchor ms-1" href="#21-进程的内存"></a></h3>
<p>每个进程都有自己的虚拟地址空间被 MMU（Memory Management Unit, 内存管理单元）(和内核)动态的转换到物理内存地址空间。这部分空间被划分成了几个部分，我们需要了解的是至少有一部分空间存放代码，一个用来存放局部变量的栈，一部分用来存放常量和全局变量的空间，以及程序的无组织空间我们称之为堆。</p>
<p>堆是一个连续的（依据虚拟地址而言）内存空间，它有三个边界：一个起始点，一个最大限度边界（通过 sys/ressource.h 中的 getrlimit(2)函数和 setrlimit(2)函数来管理）和一个被称为<code>break</code>的结束点。<code>break</code>标记了隐射内存空间的结束，也就是说，虚拟地址空间部分对应着真实的内存空间。下图表示内存组织结构</p>
<p><picture><img class="img-fluid mx-auto d-block" alt="heap" src="https://blog.liubang.cc/images/2017-03-17/heap.png#center?v=3b7bbf8ec99cb76d7d5df5d7dfe0bd84" loading="lazy" width="512" height="114" />
</picture>

</p>
<p>要想实现一个<code>malloc</code>函数，我们需要知道堆的起始点和 break 的位置，然后我们来移动 break。要做到这些，就需要用到两个系统调用，<code>brk</code>和<code>sbrk</code>。</p>

<h3 id="22-brk2和-sbrk2" data-numberify>2.2 brk(2)和 sbrk(2)<a class="anchor ms-1" href="#22-brk2和-sbrk2"></a></h3>
<p>我们可以在这些系统调用的文档中看到相关描述：</p>]]></description></item><item><title>基于c语言的编程语言开发</title><link>https://blog.liubang.cc/posts/compiler/2017-03-15-%E5%9F%BA%E4%BA%8Ec%E8%AF%AD%E8%A8%80%E7%9A%84%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91/</link><pubDate>Wed, 15 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/compiler/2017-03-15-%E5%9F%BA%E4%BA%8Ec%E8%AF%AD%E8%A8%80%E7%9A%84%E7%BC%96%E7%A8%8B%E8%AF%AD%E8%A8%80%E5%BC%80%E5%8F%91/</guid><description><![CDATA[<h2 id="preface" data-numberify>Preface<a class="anchor ms-1" href="#preface"></a></h2>
<p>当今世道，各种高级语言百花齐放。然而会有人发出这样的疑问&ndash;计算机真的能够识别这么多语言吗？稍微有点常识的人都知道，这显然是不可能滴！在计算机的世界里，他们能够直接识别的只有机器语言。然而，由于机器语言对人类不够友好，所以人们才发明了汇编，c，Java&hellip;许许多多的人类易读的编程语言，所以我个人对编程语言的理解一直是其实他们就是机器语言的语法糖，而编程语言的创造过程，就是定义一种合理的，没有二义性的语法规则，然后就是通过直接或间接的方式实现该语法到机器语言的转换过程。既然是这样的话，那么我们就很容易想到，计算机语言是一个自我完善的过程：首先我们定了一种非常简单的 x1(这里只是用来举例说明，有没有 x 语言有待考证)语言，然后用机器语言实现了这个非常简单的 x1 语言的编译器，创造了 x1 语言，实现了非常简单的新特性，然后我们再用 x1 语言(相对于机器语言较高级)实现了另一些新的特性的 x2 语言的编译器，创造了 x2 语言，&hellip;，如此下去，人们创造了汇编语言，从而创造了 c 语言，接着创造了世界上最好的语言 PHP(不知道是不是真的，反正大家都习惯这么说)。
在各种高级语言越来越强大的今天，我们可能很难再会去接触最原始的东西，高度封装确实提高了生产力，降低了学习成本，但是也使得现代程序员将太多精力花在了各种说明书上，而不清楚其本质。
毕业一年多，工作了一年多，对于计算机编程有了自己的看法，不再像在大学的时候认识的那样肤浅，反而觉得大学中学习的知识才是真正的干货，不禁感叹曾经浪费掉了大好光阴。好在陶渊明有词云：“悟已往之不谏，知来者之可追”。
闲暇之余，扒开 PHP(这里之所以是 PHP 并不因为他是世界上最好的语言，只是因为我目前从事的是 PHP 开发的工作而已)源码，了解了其内部构造和实现原理，百看不一练。今天就初步学习 yacc/lex 了，记录在我的博客中，以便以后翻阅巩固。</p>

<h2 id="过程简述" data-numberify>过程简述<a class="anchor ms-1" href="#过程简述"></a></h2>
<p>一般来说编程语言的解释执行过程如下：</p>
<p><strong>ONE</strong>. 词法分析
将源代码拆分成若干 Token 的过程</p>
<p><strong>TWO</strong>.语法分析
将 Token 构建成 Syntax Tree 的过程</p>
<p><strong>THREE</strong>.生成执行码
生成可执行文件</p>

<h2 id="yaccyet-another-compiler-compiler" data-numberify>yacc（Yet Another Compiler Compiler）<a class="anchor ms-1" href="#yaccyet-another-compiler-compiler"></a></h2>
<p>下面是 wikipedia 中对 yacc 的描述</p>
<blockquote>
<p>Yacc is a computer program for the Unix operating system. It is a Look Ahead Left-to-Right (LALR) parser generator, generating a parser, the part of a compiler that tries to make syntactic sense of the source code, specifically a LALR parser, based on an analytic grammar written in a notation similar to Backus–Naur Form (BNF). Yacc itself used to be available as the default parser generator on most Unix systems, though it has since been supplanted as the default by more recent, largely compatible, programs.</p>]]></description></item><item><title>PHP扩展开发之call_user_func原理和回调函数的实现</title><link>https://blog.liubang.cc/posts/php/2017-03-09-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8Bcall-user-func%E5%8E%9F%E7%90%86%E5%92%8C%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9E%E7%8E%B0/</link><pubDate>Thu, 09 Mar 2017 00:00:00 +0000</pubDate><guid>https://blog.liubang.cc/posts/php/2017-03-09-php%E6%89%A9%E5%B1%95%E5%BC%80%E5%8F%91%E4%B9%8Bcall-user-func%E5%8E%9F%E7%90%86%E5%92%8C%E5%9B%9E%E8%B0%83%E5%87%BD%E6%95%B0%E7%9A%84%E5%AE%9E%E7%8E%B0/</guid><description><![CDATA[<h2 id="函数调用" data-numberify>函数调用<a class="anchor ms-1" href="#函数调用"></a></h2>
<p>很多时候，我们需要通过函数名来调用函数，并传递参数，或者把匿名函数作为函数的参数传递，实现回调。当我们在遇到这样的需求的时候，用 php 代码实现起来肯定是非常容易和简单的。但是，当我们在用 c 语言编写 php 扩展的时候，如何来实现这样的功能呢？下面就一起来深入了解 php 内核，看看如何实现。</p>
<p>在 Zend 引擎中，给我们提供了<code>zend_call_function</code>,<code>call_user_function</code>以及<code>call_user_function_ex</code>函数来帮助我们实现函数调用。在<code>zend_API.h</code>文件中，我们可以看到如下函数原型的声明：</p>
<!-- more -->
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-1">1</a></span><span><span style="color:#e06c75">ZEND_API</span> <span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">zend_call_function</span>(<span style="color:#e06c75">zend_fcall_info</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">fci</span>, <span style="color:#e06c75">zend_fcall_info_cache</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">fci_cache</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-2">2</a></span><span><span style="color:#e06c75">ZEND_API</span> <span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">call_user_function</span>(<span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_table</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">object_pp</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_name</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">retval_ptr</span>, <span style="color:#e06c75">zend_uint</span> <span style="color:#e06c75">param_count</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">params</span>[] <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-0-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-0-3">3</a></span><span><span style="color:#e06c75">ZEND_API</span> <span style="color:#e5c07b">int</span> <span style="color:#61afef;font-weight:bold">call_user_function_ex</span>(<span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_table</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">object_pp</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_name</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">retval_ptr_ptr</span>, <span style="color:#e06c75">zend_uint</span> <span style="color:#e06c75">param_count</span>, <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">params</span>[], <span style="color:#e5c07b">int</span> <span style="color:#e06c75">no_separation</span>, <span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">symbol_table</span> <span style="color:#e06c75">TSRMLS_DC</span>);
</span></span></code></pre></div><p>从函数的参数上来看，显然<code>zend_call_function</code>需要的参数很少，而其他两个都需要一堆参数，所以，我们可能会想，达到相同的效果为什么参数上有如此大的区别，于是带着这个疑问我们来解刨<code>zend_fcall_info</code>结构体。同样在<code>zend_API.h</code>中会看到如下结构体的定义：</p>
<div class="highlight"><pre tabindex="0" style="color:#abb2bf;background-color:#282c34;-moz-tab-size:2;-o-tab-size:2;tab-size:2;-webkit-text-size-adjust:none;"><code class="language-c" data-lang="c"><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-1"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-1"> 1</a></span><span><span style="color:#c678dd">typedef</span> <span style="color:#c678dd">struct</span> <span style="color:#e06c75">_zend_fcall_info</span> {
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-2"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-2"> 2</a></span><span>        <span style="color:#e5c07b">size_t</span> <span style="color:#e06c75">size</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-3"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-3"> 3</a></span><span>        <span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_table</span>; <span style="color:#7f848e">//函数表
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-4"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-4"> 4</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">function_name</span>;	   <span style="color:#7f848e">//函数，可以是函数名，也可以直接是匿名函数本身
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-5"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-5"> 5</a></span><span>        <span style="color:#e06c75">HashTable</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">symbol_table</span>;   <span style="color:#7f848e">//符号表
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-6"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-6"> 6</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">**</span><span style="color:#e06c75">retval_ptr_ptr</span>;	   <span style="color:#7f848e">//返回值
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-7"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-7"> 7</a></span><span>        <span style="color:#e06c75">zend_uint</span> <span style="color:#e06c75">param_count</span>;     <span style="color:#7f848e">//参数个数
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-8"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-8"> 8</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">***</span><span style="color:#e06c75">params</span>; 		   <span style="color:#7f848e">//参数，数组
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-9"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-9"> 9</a></span><span>        <span style="color:#e06c75">zval</span> <span style="color:#56b6c2">*</span><span style="color:#e06c75">object_ptr</span>;		   <span style="color:#7f848e">//调用对象方法时候需要传调用的对象
</span></span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-10"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-10">10</a></span><span>        <span style="color:#e06c75">zend_bool</span> <span style="color:#e06c75">no_separation</span>;
</span></span><span style="display:flex;"><span style="white-space:pre;-webkit-user-select:none;user-select:none;margin-right:0.4em;padding:0 0.4em 0 0.4em;color:#55595f" id="hl-1-11"><a style="outline:none;text-decoration:none;color:inherit" href="#hl-1-11">11</a></span><span>} <span style="color:#e06c75">zend_fcall_info</span>;
</span></span></code></pre></div><p>不难发现，原来是把相关字段封装到了结构体中了，所以显得参数数量少，实际上该有的都有。</p>]]></description></item></channel></rss>