<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Cherno on 随记</title><link>https://blog.liuyi2026.asia/zh/tags/cherno/</link><description>Recent content in Cherno on 随记</description><generator>Hugo</generator><language>zh</language><lastBuildDate>Tue, 05 May 2026 23:13:37 +0800</lastBuildDate><atom:link href="https://blog.liuyi2026.asia/zh/tags/cherno/index.xml" rel="self" type="application/rss+xml"/><item><title>23批量渲染对象</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/23%E6%89%B9%E9%87%8F%E6%B8%B2%E6%9F%93%E5%AF%B9%E8%B1%A1/</link><pubDate>Tue, 05 May 2026 23:13:37 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/23%E6%89%B9%E9%87%8F%E6%B8%B2%E6%9F%93%E5%AF%B9%E8%B1%A1/</guid><description>&lt;p>核心内容是如何通过修改 &lt;mark>MVP（模型-视图-投影）矩阵&lt;/mark> 在不同位置多次绘制同一个物体，并初步探讨了性能优化的思路。&lt;/p>
&lt;h1 id="第-23-集在-opengl-中渲染多个物体">第 23 集：在 OpenGL 中渲染多个物体&lt;a class="anchor" href="#%e7%ac%ac-23-%e9%9b%86%e5%9c%a8-opengl-%e4%b8%ad%e6%b8%b2%e6%9f%93%e5%a4%9a%e4%b8%aa%e7%89%a9%e4%bd%93">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>[00:00:00 - 01:25] 核心目标与现状回顾&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>回顾之前只能在屏幕上渲染一个 Logo。&lt;/li>
&lt;li>目标：在不同位置渲染两个或多个相同的物体。&lt;/li>
&lt;li>解决 ImGui 鼠标位置偏移的小技巧：切换 GPU 驱动（由 Intel 切换至 Nvidia）解决了一些驱动层面的显示问题。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>渲染原理深究：Shader、VAO 与 Draw Call&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>&lt;mark>Shader (Program)：&lt;/mark> 告诉 GPU “如何”绘制数据，而不仅仅是光照。&lt;/li>
&lt;li>&lt;mark>Vertex Array (VAO)：&lt;/mark> 包含实际的顶点数据（位置、纹理坐标等）。&lt;/li>
&lt;li>&lt;mark>Index Buffer：&lt;/mark> 决定顶点的组合顺序。&lt;/li>
&lt;li>&lt;mark>Draw Call：&lt;/mark> 调用 &lt;code>glDrawElements&lt;/code>，结合 Shader 和数据完成最终的光栅化。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>如何改变物体位置？（两种方案）&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>&lt;mark>方案 A（低效）：&lt;/mark> 为每个物体创建独立的顶点缓冲区（Vertex Buffer）。缺点：浪费显存，频繁切换 Buffer 速度慢。&lt;/li>
&lt;li>&lt;mark>方案 B（推荐）：&lt;/mark> 保持顶点数据不变，但在每次绘制前修改 &lt;mark>Uniform 变量&lt;/mark>（即 Model 矩阵）。通过矩阵变换将同一组顶点映射到屏幕的不同位置。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>顶点坐标的标准化归零&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>为了方便平移，将顶点的原始坐标从 &lt;code>[100, 200]&lt;/code> 修改为以原点为中心的 &lt;code>[-50, 50]&lt;/code>。&lt;/li>
&lt;li>这样做的好处是物体的 &lt;mark>Origin（原点）&lt;/mark> 位于其中心，应用平移矩阵时坐标计算更直观。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 定义三角形的顶点坐标（CPU 内存）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">float&lt;/span> positions[] &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">50.0f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">50.0f&lt;/span>,&lt;span style="color:#ae81ff">0.0f&lt;/span>,&lt;span style="color:#ae81ff">0.0f&lt;/span>,&lt;span style="color:#75715e">//0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#ae81ff">50.0f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">50.0f&lt;/span>,&lt;span style="color:#ae81ff">1.0f&lt;/span>,&lt;span style="color:#ae81ff">0.0f&lt;/span>,&lt;span style="color:#75715e">//1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#ae81ff">50.0f&lt;/span>, &lt;span style="color:#ae81ff">50.0f&lt;/span>,&lt;span style="color:#ae81ff">1.0f&lt;/span>,&lt;span style="color:#ae81ff">1.0f&lt;/span>,&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//0.5f, 0.5f,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">50.0f&lt;/span>, &lt;span style="color:#ae81ff">50.0f&lt;/span>,&lt;span style="color:#ae81ff">0.0f&lt;/span>,&lt;span style="color:#ae81ff">1.0f&lt;/span>,&lt;span style="color:#75715e">//3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//-0.5f, -0.5f,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//while之前的代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glm&lt;span style="color:#f92672">::&lt;/span>vec3 translationA(&lt;span style="color:#ae81ff">200&lt;/span>, &lt;span style="color:#ae81ff">200&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		glm&lt;span style="color:#f92672">::&lt;/span>vec3 translationB(&lt;span style="color:#ae81ff">400&lt;/span>, &lt;span style="color:#ae81ff">200&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//while代码块内的代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">if&lt;/span> (r &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">1.0f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (r &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			r &lt;span style="color:#f92672">+=&lt;/span> increment;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//绘图前重新绑定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			shader.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//imgui:这里吧mvp相关代码移到while循环中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//向右向上移动200
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				glm&lt;span style="color:#f92672">::&lt;/span>mat4 model &lt;span style="color:#f92672">=&lt;/span> glm&lt;span style="color:#f92672">::&lt;/span>translate(glm&lt;span style="color:#f92672">::&lt;/span>mat4(&lt;span style="color:#ae81ff">1.0f&lt;/span>), translationA);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				glm&lt;span style="color:#f92672">::&lt;/span>mat4 mvp &lt;span style="color:#f92672">=&lt;/span> proj &lt;span style="color:#f92672">*&lt;/span> view &lt;span style="color:#f92672">*&lt;/span> model;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				shader.SetUniformMat4f(&lt;span style="color:#e6db74">&amp;#34;u_MVP&amp;#34;&lt;/span>, mvp);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//在u_Color的位置上设置数值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//shader.SetUniform4f(&amp;#34;u_Color&amp;#34;, r, 0.3f, 0.0f, 1.0f);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//========设置uniform========
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				renderer.Draw(va, ib, shader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				&lt;span style="color:#75715e">//批量渲染对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				glm&lt;span style="color:#f92672">::&lt;/span>mat4 model &lt;span style="color:#f92672">=&lt;/span> glm&lt;span style="color:#f92672">::&lt;/span>translate(glm&lt;span style="color:#f92672">::&lt;/span>mat4(&lt;span style="color:#ae81ff">1.0f&lt;/span>), translationB);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				glm&lt;span style="color:#f92672">::&lt;/span>mat4 mvp &lt;span style="color:#f92672">=&lt;/span> proj &lt;span style="color:#f92672">*&lt;/span> view &lt;span style="color:#f92672">*&lt;/span> model;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				shader.SetUniformMat4f(&lt;span style="color:#e6db74">&amp;#34;u_MVP&amp;#34;&lt;/span>, mvp);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				renderer.Draw(va, ib, shader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//{}//小窗口前面的代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="img/ly-20260506220636032.png" alt="" />&lt;/p></description></item><item><title>22关于ImGui</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/22%E5%85%B3%E4%BA%8EImGui/</link><pubDate>Tue, 28 Apr 2026 22:49:11 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/22%E5%85%B3%E4%BA%8EImGui/</guid><description>&lt;p>第 22 集是 Cherno 系列中非常爽的一集，因为它让你告别了“硬编码”坐标的痛苦，转而使用&lt;mark>可视化 UI&lt;/mark> 来直接操控显卡里的数据。&lt;/p>
&lt;h1 id="代码">代码&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;p>
&lt;a target="_blank" href="https://github.com/ocornut/imgui">https://github.com/ocornut/imgui&lt;/a> 下载1.6版本，和视频中保持一致&lt;/p>
&lt;p>根目录下所有.h和.cpp文件，以及&lt;code>examples\opengl3_example&lt;/code>文件夹中的.h和.cpp文件都复制到项目中 &lt;del>不要include main.cpp文件&lt;/del> 。&lt;/p>
&lt;p>&lt;img src="img/ly-20260503213446407.png" alt="" />&lt;/p>
&lt;p>修改&lt;code>imgui_impl_glfw_gl3.cpp&lt;/code>中开头的 &lt;code>#include &amp;lt;GL/gl3w.h&amp;gt;&lt;/code> 为&lt;code>#include &amp;lt;GL/glew.h&amp;gt; &lt;/code>&lt;/p>
&lt;h2 id="添加头文件">添加头文件&lt;a class="anchor" href="#%e6%b7%bb%e5%8a%a0%e5%a4%b4%e6%96%87%e4%bb%b6">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;imgui_1.60/imgui.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;imgui_1.60/imgui_impl_glfw_gl3.h&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="shader后的修改">shader后的修改&lt;a class="anchor" href="#shader%e5%90%8e%e7%9a%84%e4%bf%ae%e6%94%b9">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//imGui创建上下文
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// Setup ImGui binding
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ImGui&lt;span style="color:#f92672">::&lt;/span>CreateContext();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//windows ,告诉 ImGui 你的程序窗口在哪里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//允许 ImGui 自动接管窗口的回调函数（比如鼠标点击、滚轮滚动）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ImGui_ImplGlfwGL3_Init(window, true);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//设置 UI 的主题配色
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ImGui&lt;span style="color:#f92672">::&lt;/span>StyleColorsDark();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//解决白屏问题2：在进入 while 循环前，手动清一次屏并交换缓冲
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//设置“清除颜色”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glClearColor(&lt;span style="color:#ae81ff">0.2f&lt;/span>, &lt;span style="color:#ae81ff">0.3f&lt;/span>, &lt;span style="color:#ae81ff">0.3f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//用上面选好的“油漆”填满整个颜色缓冲区（Color Buffer）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glClear(GL_COLOR_BUFFER_BIT);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//交换缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwSwapBuffers(window); &lt;span style="color:#75715e">// 这一步把“深绿色”推送到显卡
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//解决白屏问题3：最后才显示窗口
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwShowWindow(window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">bool&lt;/span> show_demo_window &lt;span style="color:#f92672">=&lt;/span> true;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">bool&lt;/span> show_another_window &lt;span style="color:#f92672">=&lt;/span> false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		ImVec4 clear_color &lt;span style="color:#f92672">=&lt;/span> ImVec4(&lt;span style="color:#ae81ff">0.45f&lt;/span>, &lt;span style="color:#ae81ff">0.55f&lt;/span>, &lt;span style="color:#ae81ff">0.60f&lt;/span>, &lt;span style="color:#ae81ff">1.00f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		glm&lt;span style="color:#f92672">::&lt;/span>vec3 translation(&lt;span style="color:#ae81ff">200&lt;/span>, &lt;span style="color:#ae81ff">200&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 游戏/渲染主循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">while&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>glfwWindowShouldClose(window))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 清理屏幕颜色缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			renderer.Clear();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ImGui_ImplGlfwGL3_NewFrame();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//必须先绑定program，因为vao不负责着色器程序的切换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//va.Bind();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">if&lt;/span> (r &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">1.0f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (r &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			r &lt;span style="color:#f92672">+=&lt;/span> increment;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//绘图前重新绑定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			shader.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//imgui:这里吧mvp相关代码移到while循环中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//向右向上移动200
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glm&lt;span style="color:#f92672">::&lt;/span>mat4 model &lt;span style="color:#f92672">=&lt;/span> glm&lt;span style="color:#f92672">::&lt;/span>translate(glm&lt;span style="color:#f92672">::&lt;/span>mat4(&lt;span style="color:#ae81ff">1.0f&lt;/span>), translation);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			glm&lt;span style="color:#f92672">::&lt;/span>mat4 mvp &lt;span style="color:#f92672">=&lt;/span> proj &lt;span style="color:#f92672">*&lt;/span> view &lt;span style="color:#f92672">*&lt;/span> model;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			shader.SetUniformMat4f(&lt;span style="color:#e6db74">&amp;#34;u_MVP&amp;#34;&lt;/span>, mvp);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//在u_Color的位置上设置数值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//shader.SetUniform4f(&amp;#34;u_Color&amp;#34;, r, 0.3f, 0.0f, 1.0f);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//========设置uniform========
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			renderer.Draw(va, ib, shader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//小窗口
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">float&lt;/span> f &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> counter &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				ImGui&lt;span style="color:#f92672">::&lt;/span>Text(&lt;span style="color:#e6db74">&amp;#34;Hello, world!&amp;#34;&lt;/span>); &lt;span style="color:#75715e">// Display some text (you can use a format string too)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//这里传入translation.x的地址，imgui会在这个地址上修改值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				&lt;span style="color:#75715e">//第一个参数是标签，表示在imgui界面上显示的名字，第二个参数是要修改的值的地址，后面是这个值的范围
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				ImGui&lt;span style="color:#f92672">::&lt;/span>SliderFloat3(&lt;span style="color:#e6db74">&amp;#34;Translation&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>translation.x, &lt;span style="color:#ae81ff">0.0f&lt;/span>, &lt;span style="color:#ae81ff">960.0f&lt;/span>); &lt;span style="color:#75715e">// Edit 1 float using a slider from 0.0f to 1.0f 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				ImGui&lt;span style="color:#f92672">::&lt;/span>SliderFloat(&lt;span style="color:#e6db74">&amp;#34;float&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>f, &lt;span style="color:#ae81ff">0.0f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>); &lt;span style="color:#75715e">// Edit 1 float using a slider from 0.0f to 1.0f 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				ImGui&lt;span style="color:#f92672">::&lt;/span>ColorEdit3(&lt;span style="color:#e6db74">&amp;#34;clear color&amp;#34;&lt;/span>, (&lt;span style="color:#66d9ef">float&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">&amp;amp;&lt;/span>clear_color); &lt;span style="color:#75715e">// Edit 3 floats representing a color
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				ImGui&lt;span style="color:#f92672">::&lt;/span>Checkbox(&lt;span style="color:#e6db74">&amp;#34;Demo Window&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>show_demo_window); &lt;span style="color:#75715e">// Edit bools storing our windows open/close state
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>				ImGui&lt;span style="color:#f92672">::&lt;/span>Checkbox(&lt;span style="color:#e6db74">&amp;#34;Another Window&amp;#34;&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>show_another_window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				&lt;span style="color:#66d9ef">if&lt;/span> (ImGui&lt;span style="color:#f92672">::&lt;/span>Button(&lt;span style="color:#e6db74">&amp;#34;Button&amp;#34;&lt;/span>)) &lt;span style="color:#75715e">// Buttons return true when clicked (NB: most widgets return true when edited/activated)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>					counter&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				ImGui&lt;span style="color:#f92672">::&lt;/span>SameLine();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				ImGui&lt;span style="color:#f92672">::&lt;/span>Text(&lt;span style="color:#e6db74">&amp;#34;counter = %d&amp;#34;&lt;/span>, counter);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				ImGui&lt;span style="color:#f92672">::&lt;/span>Text(&lt;span style="color:#e6db74">&amp;#34;Application average %.3f ms/frame (%.1f FPS)&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">1000.0f&lt;/span> &lt;span style="color:#f92672">/&lt;/span> ImGui&lt;span style="color:#f92672">::&lt;/span>GetIO().Framerate, ImGui&lt;span style="color:#f92672">::&lt;/span>GetIO().Framerate);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//imgui:这里吧mvp相关代码移到while循环中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//向右向上移动200
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glm&lt;span style="color:#f92672">::&lt;/span>mat4 model &lt;span style="color:#f92672">=&lt;/span> glm&lt;span style="color:#f92672">::&lt;/span>translate(glm&lt;span style="color:#f92672">::&lt;/span>mat4(&lt;span style="color:#ae81ff">1.0f&lt;/span>), translation);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			glm&lt;span style="color:#f92672">::&lt;/span>mat4 mvp &lt;span style="color:#f92672">=&lt;/span> proj &lt;span style="color:#f92672">*&lt;/span> view &lt;span style="color:#f92672">*&lt;/span> model;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			shader.SetUniformMat4f(&lt;span style="color:#e6db74">&amp;#34;u_MVP&amp;#34;&lt;/span>, mvp);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ImGui&lt;span style="color:#f92672">::&lt;/span>Render();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			ImGui_ImplGlfwGL3_RenderDrawData(ImGui&lt;span style="color:#f92672">::&lt;/span>GetDrawData());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 交换前后缓冲区以刷新画面
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glfwSwapBuffers(window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 轮询并处理窗口事件（如键盘输入、关闭动作）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glfwPollEvents();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//最后解绑vao
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//glBindVertexArray(0);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//=======imgui添加============
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ImGui_ImplGlfwGL3_Shutdown();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 退出前清理资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//glfwTerminate会破坏Context，导致析构函数中的glGetError()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//返回一个OpenGL错误
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glfwTerminate();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="img/ly-20260505220751808.png" alt="" />&lt;/p></description></item><item><title>21关于模型视图投影矩阵</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/21%E5%85%B3%E4%BA%8E%E6%A8%A1%E5%9E%8B%E8%A7%86%E5%9B%BE%E6%8A%95%E5%BD%B1%E7%9F%A9%E9%98%B5/</link><pubDate>Mon, 27 Apr 2026 22:05:18 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/21%E5%85%B3%E4%BA%8E%E6%A8%A1%E5%9E%8B%E8%A7%86%E5%9B%BE%E6%8A%95%E5%BD%B1%E7%9F%A9%E9%98%B5/</guid><description>&lt;p>第 21 集通常是 Cherno 教程中从“固定画面”转向“动态交互”的关键点，也是将 &lt;mark>M、V、P&lt;/mark> 三者真正融合进代码的时刻。&lt;/p>
&lt;p>按照&lt;mark>程序运行的时间线&lt;/mark>，我们可以把这套复杂的逻辑分为以下阶段：&lt;/p>
&lt;h1 id="1-初始化阶段建立尺子-p">1. 初始化阶段：建立“尺子” (P)&lt;a class="anchor" href="#1-%e5%88%9d%e5%a7%8b%e5%8c%96%e9%98%b6%e6%ae%b5%e5%bb%ba%e7%ab%8b%e5%b0%ba%e5%ad%90-p">#&lt;/a>&lt;/h1>
&lt;p>在程序启动时，你先定义了&lt;mark>投影矩阵 (Projection Matrix)&lt;/mark>。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>动作&lt;/mark>：&lt;code>glm::ortho(0.0f, 960.0f, 0.0f, 540.0f, -1.0f, 1.0f)&lt;/code>。&lt;/li>
&lt;li>&lt;mark>目的&lt;/mark>：建立一套“像素坐标系”。它就像一把尺子，告诉 GPU：“以后我给你 这个数，你就把它当成屏幕的最右边。”&lt;/li>
&lt;li>&lt;mark>状态&lt;/mark>：此时你还没决定看哪，也没决定物体在哪。&lt;/li>
&lt;/ul>
&lt;h1 id="2-空间布局阶段摆放相机与物体-v--m">2. 空间布局阶段：摆放相机与物体 (V &amp;amp; M)&lt;a class="anchor" href="#2-%e7%a9%ba%e9%97%b4%e5%b8%83%e5%b1%80%e9%98%b6%e6%ae%b5%e6%91%86%e6%94%be%e7%9b%b8%e6%9c%ba%e4%b8%8e%e7%89%a9%e4%bd%93-v--m">#&lt;/a>&lt;/h1>
&lt;p>在每一帧渲染开始前，你需要在 CPU 中计算当前的位置。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>视图矩阵 (View Matrix)&lt;/mark>：
&lt;ul>
&lt;li>&lt;mark>动作&lt;/mark>：&lt;code>glm::translate(glm::mat4(1.0f), glm::vec3(x, y, z))&lt;/code>（通常是反向平移）。&lt;/li>
&lt;li>&lt;mark>目的&lt;/mark>：模拟摄像机的移动。如果你想让相机往右移，代码里其实是把整个世界往左拽。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>模型矩阵 (Model Matrix)&lt;/mark>：
&lt;ul>
&lt;li>&lt;mark>动作&lt;/mark>：&lt;code>glm::translate&lt;/code> 或 &lt;code>glm::rotate&lt;/code>。&lt;/li>
&lt;li>&lt;mark>目的&lt;/mark>：决定这个特定的物体（比如那个 logo）在世界里的具体坐标、旋转角度和缩放比例。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="分工">分工&lt;a class="anchor" href="#%e5%88%86%e5%b7%a5">#&lt;/a>&lt;/h2>
&lt;p>&lt;mark>旋转、缩放、平移，这“三兄弟”通常全部都在 M（Model 矩阵）里完成。&lt;/mark>&lt;/p>
&lt;p>虽然在数学上，你可以把它们放进任何矩阵，但在图形学的标准逻辑（即第 21 集所讲的逻辑）中，它们分工非常明确：&lt;/p>
&lt;h3 id="1-m-model-矩阵--物体自己的属性">1. M (Model 矩阵) —— 物体自己的“属性”&lt;a class="anchor" href="#1-m-model-%e7%9f%a9%e9%98%b5--%e7%89%a9%e4%bd%93%e8%87%aa%e5%b7%b1%e7%9a%84%e5%b1%9e%e6%80%a7">#&lt;/a>&lt;/h3>
&lt;p>&lt;mark>适用范围：旋转、缩放、平移（全占了）。&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>&lt;mark>平移 (Translation)&lt;/mark>：你想把方块放到屏幕左边还是右边？&lt;/li>
&lt;li>&lt;mark>旋转 (Rotation)&lt;/mark>：你想让方块站着还是躺着？&lt;/li>
&lt;li>&lt;mark>缩放 (Scaling)&lt;/mark>：你想让方块变大还是变小？&lt;/li>
&lt;/ul>
&lt;p>&lt;mark>核心逻辑&lt;/mark>：Model 矩阵负责定义&lt;mark>物体在世界里的样子&lt;/mark>。一个 logo 无论它怎么转、怎么挪，那都是它作为一个“物体”的行为。&lt;/p></description></item><item><title>20关于投影矩阵</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/20%E5%85%B3%E4%BA%8E%E6%8A%95%E5%BD%B1%E7%9F%A9%E9%98%B5/</link><pubDate>Fri, 24 Apr 2026 16:44:10 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/20%E5%85%B3%E4%BA%8E%E6%8A%95%E5%BD%B1%E7%9F%A9%E9%98%B5/</guid><description>&lt;p>既然已经学到了第 20 集（通常是 &lt;mark>MVP 矩阵&lt;/mark> 的收尾和调试），我们可以把这套复杂的“坐标变换流水线”按时间顺序梳理一遍。&lt;/p>
&lt;p>这不仅是代码的运行顺序，也是你大脑中理解 OpenGL 坐标变换的“心路历程”：&lt;/p>
&lt;h1 id="诞生模型空间-model-space">诞生：模型空间 (Model Space)&lt;a class="anchor" href="#%e8%af%9e%e7%94%9f%e6%a8%a1%e5%9e%8b%e7%a9%ba%e9%97%b4-model-space">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>时间点&lt;/mark>：你在 &lt;code>main&lt;/code> 函数里定义 &lt;code>float positions[]&lt;/code> 的那一刻。&lt;/li>
&lt;li>&lt;mark>状态&lt;/mark>：此时的坐标是纯粹的几何数据。比如矩形宽 &lt;code>100&lt;/code>，高 &lt;code>100&lt;/code>。&lt;/li>
&lt;li>&lt;mark>你的认知&lt;/mark>：这些数字没有单位，它们只是相对于物体中心（原点）的位置。&lt;/li>
&lt;/ul>
&lt;h1 id="变换世界空间-world-space--m-model-matrix">变换：世界空间 (World Space) —— M (Model Matrix)&lt;a class="anchor" href="#%e5%8f%98%e6%8d%a2%e4%b8%96%e7%95%8c%e7%a9%ba%e9%97%b4-world-space--m-model-matrix">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>时间点&lt;/mark>：在渲染循环中，当你想要移动、旋转这个矩形时。&lt;/li>
&lt;li>&lt;mark>动作&lt;/mark>：给模型乘以一个 &lt;mark>Model 矩阵&lt;/mark>。&lt;/li>
&lt;li>&lt;mark>结果&lt;/mark>：矩形被“摆放”到了虚拟世界里的某个位置（比如 ）。&lt;/li>
&lt;/ul>
&lt;h1 id="观察摄像机空间-view-space--v-view-matrix">观察：摄像机空间 (View Space) —— V (View Matrix)&lt;a class="anchor" href="#%e8%a7%82%e5%af%9f%e6%91%84%e5%83%8f%e6%9c%ba%e7%a9%ba%e9%97%b4-view-space--v-view-matrix">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>时间点&lt;/mark>：你想决定从哪个角度看这个世界。&lt;/li>
&lt;li>&lt;mark>动作&lt;/mark>：乘以 &lt;mark>View 矩阵&lt;/mark>（就像把摄像机架好）。&lt;/li>
&lt;li>&lt;mark>结果&lt;/mark>：所有物体的坐标现在变成了“相对于摄像机”的位置。如果摄像机向右移，物体在坐标系中就向左移。&lt;/li>
&lt;/ul>
&lt;h1 id="关键投影变换-projection-space--p-projection-matrix">关键：投影变换 (Projection Space) —— P (Projection Matrix)&lt;a class="anchor" href="#%e5%85%b3%e9%94%ae%e6%8a%95%e5%bd%b1%e5%8f%98%e6%8d%a2-projection-space--p-projection-matrix">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>时间点&lt;/mark>：&lt;mark>这就是你在第 19-20 集重点攻克的部分。&lt;/mark>&lt;/li>
&lt;li>&lt;mark>动作&lt;/mark>：乘以你定义的 &lt;code>glm::ortho&lt;/code>（正交投影）矩阵。&lt;/li>
&lt;li>&lt;mark>核心逻辑&lt;/mark>：
&lt;ul>
&lt;li>&lt;mark>矩阵的工作&lt;/mark>：它把你在正交矩阵里定义的范围（比如 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0&lt;/mn>&lt;mo>∼&lt;/mo>&lt;mn>800&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0 \sim 800&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 ）&lt;mark>强行压缩&lt;/mark>到 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">[&lt;/mo>&lt;mo>−&lt;/mo>&lt;mn>1.0&lt;/mn>&lt;mo separator="true">,&lt;/mo>&lt;mn>1.0&lt;/mn>&lt;mo stretchy="false">]&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">[-1.0, 1.0]&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 。&lt;/li>
&lt;li>&lt;mark>Shader 执行&lt;/mark>：在 Vertex Shader 里执行 &lt;code>u_MVP * position&lt;/code>。&lt;/li>
&lt;li>&lt;mark>赋值&lt;/mark>：结果存入 &lt;code>gl_Position&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="正交投影和透视投影">正交投影和透视投影&lt;a class="anchor" href="#%e6%ad%a3%e4%ba%a4%e6%8a%95%e5%bd%b1%e5%92%8c%e9%80%8f%e8%a7%86%e6%8a%95%e5%bd%b1">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>正交投影：渲染UI（用户界面），2D游戏（通常）等&lt;/li>
&lt;li>透视投影：3D，第一视角&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="img/ly-20260426000611720.png" alt="" />&lt;/p></description></item><item><title>19关于数学库</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/19%E5%85%B3%E4%BA%8E%E6%95%B0%E5%AD%A6%E5%BA%93/</link><pubDate>Tue, 07 Apr 2026 23:00:29 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/19%E5%85%B3%E4%BA%8E%E6%95%B0%E5%AD%A6%E5%BA%93/</guid><description>&lt;h1 id="总结">总结&lt;a class="anchor" href="#%e6%80%bb%e7%bb%93">#&lt;/a>&lt;/h1>
&lt;p>引入 &lt;mark>数学库 (Math Library)&lt;/mark>，特别是处理&lt;mark>向量（Vector）和矩阵（Matrix）运算&lt;/mark>。对于图形学来说，数学就是“画笔”，而矩阵就是“坐标转换器”。&lt;/p>
&lt;p>以下是按时间线整理的核心知识点总结：&lt;/p>
&lt;h2 id="为什么需要第三方数学库">为什么需要第三方数学库？&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81%e7%ac%ac%e4%b8%89%e6%96%b9%e6%95%b0%e5%ad%a6%e5%ba%93">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>原生局限&lt;/mark>：C++ 标准库没有提供专门针对图形学的向量（如 &lt;code>vec3&lt;/code>）和矩阵（如 &lt;code>mat4&lt;/code>）运算。&lt;/li>
&lt;li>&lt;mark>GLSL 同步&lt;/mark>：我们需要在 CPU 端计算好矩阵，然后传递给 Shader。如果 CPU 端的数学库逻辑（比如数据排布）能与 Shader 中的 GLSL 保持一致，开发效率会极高。&lt;/li>
&lt;li>&lt;mark>GLM 的选择&lt;/mark>：Cherno 选择了 &lt;mark>GLM (OpenGL Mathematics)&lt;/mark>。它是一个 &lt;mark>Header-only&lt;/mark>（仅头文件）的库，设计思路完全模仿 GLSL，且与 OpenGL 兼容性完美。&lt;/li>
&lt;/ul>
&lt;p>&lt;code>https://github.com/g-truc/glm/releases/tag/1.0.3&lt;/code>&lt;/p>
&lt;p>项目属性中设置：&lt;/p>
&lt;p>&lt;img src="img/ly-20260411231545098.png" alt="" />&lt;/p>
&lt;p>之后这里把&lt;code>Texture.cpp&lt;/code>的头文件前几行改为&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Texture.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Renderer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;stb_image/stb_image.h&amp;#34;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">//去除了vendor/
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>把 glm这个文件夹 (ui-右键)&lt;code>include&lt;/code>&lt;/li>
&lt;li>把 &lt;code>glm/detail/glm.cpp&lt;/code> 和 &lt;code>glm/glm.cppm&lt;/code> (ui-右键)&lt;code>exclude project &lt;/code>&lt;/li>
&lt;/ol>
&lt;h2 id="向量与矩阵的基本概念">向量与矩阵的基本概念&lt;a class="anchor" href="#%e5%90%91%e9%87%8f%e4%b8%8e%e7%9f%a9%e9%98%b5%e7%9a%84%e5%9f%ba%e6%9c%ac%e6%a6%82%e5%bf%b5">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>向量 (Vector)&lt;/mark>：&lt;mark>不仅代表位置，还代表方向&lt;/mark>。在 2D 中是 &lt;code>vec2&lt;/code>，3D 中是 &lt;code>vec3&lt;/code>，带上齐次坐标则是 &lt;code>vec4&lt;/code>。&lt;/li>
&lt;li>&lt;mark>矩阵 (Matrix)&lt;/mark>：图形学中的“魔法方阵”。&lt;code>mat4&lt;/code>（4x4 矩阵）可以同时包含 &lt;mark>旋转 (Rotation)&lt;/mark>、&lt;mark>平移 (Translation)&lt;/mark> 和 &lt;mark>缩放 (Scale)&lt;/mark> 信息。&lt;/li>
&lt;/ul>
&lt;h2 id="正交投影矩阵-orthographic-projection">正交投影矩阵 (Orthographic Projection)&lt;a class="anchor" href="#%e6%ad%a3%e4%ba%a4%e6%8a%95%e5%bd%b1%e7%9f%a9%e9%98%b5-orthographic-projection">#&lt;/a>&lt;/h2>
&lt;p>这是本集的实战重点。Cherno 引入了 &lt;code>glm::ortho&lt;/code> 函数：&lt;/p></description></item><item><title>18关于混合</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/18%E5%85%B3%E4%BA%8E%E6%B7%B7%E5%90%88/</link><pubDate>Mon, 06 Apr 2026 23:21:41 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/18%E5%85%B3%E4%BA%8E%E6%B7%B7%E5%90%88/</guid><description>&lt;p>这一集是关于如何处理==透明度（Alpha Channel）==的关键。当两个物体重叠时，GPU 如何决定最终像素的颜色？这就是“混合”要解决的问题。&lt;/p>
&lt;h1 id="问题的引入为什么我的图片有黑边">问题的引入：为什么我的图片有“黑边”？&lt;a class="anchor" href="#%e9%97%ae%e9%a2%98%e7%9a%84%e5%bc%95%e5%85%a5%e4%b8%ba%e4%bb%80%e4%b9%88%e6%88%91%e7%9a%84%e5%9b%be%e7%89%87%e6%9c%89%e9%bb%91%e8%be%b9">#&lt;/a>&lt;/h1>
&lt;p>在加载带透明通道的 &lt;code>.png&lt;/code> 纹理时，如果不开启混合，透明区域通常会显示为&lt;mark>纯黑色&lt;/mark>或&lt;mark>纯白色&lt;/mark>。这是因为：&lt;/p>
&lt;ul>
&lt;li>默认情况下，OpenGL 只是简单地用新像素 ==覆盖（Overwrite）==旧像素。&lt;/li>
&lt;li>即使你的纹理有 Alpha 值（例如 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0.0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0.0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 ），如果不告诉 OpenGL 如何处理它，它依然会把这个“透明”的像素颜色画上去。&lt;/li>
&lt;/ul>
&lt;h1 id="开启混合-enable-blending">开启混合 (Enable Blending)&lt;a class="anchor" href="#%e5%bc%80%e5%90%af%e6%b7%b7%e5%90%88-enable-blending">#&lt;/a>&lt;/h1>
&lt;p>OpenGL 是一个状态机，混合功能默认是关闭的。你必须手动开启：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scss" data-lang="scss">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">GLCall&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#f92672">glEnable&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#f92672">GL_BLEND&lt;/span>&lt;span style="color:#f92672">))&lt;/span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>开启后，你需要定义&lt;mark>混合函数（Blend Function）&lt;/mark>，即告诉 OpenGL：“拿新颜色（源）和旧颜色（目标）怎么算？”&lt;/p>
&lt;h1 id="核心公式混合方程式">核心公式：混合方程式&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e5%85%ac%e5%bc%8f%e6%b7%b7%e5%90%88%e6%96%b9%e7%a8%8b%e5%bc%8f">#&lt;/a>&lt;/h1>
&lt;p>这是这一集最硬核的数学部分。OpenGL 计算最终像素颜色的公式如下：&lt;/p>

 
 
 
 
 
 &lt;div class="math-block" style="margin: 1rem 0; overflow-x: auto;">
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML" display="block">&lt;semantics>&lt;mrow>&lt;msub>&lt;mi>C&lt;/mi>&lt;mrow>&lt;mi>r&lt;/mi>&lt;mi>e&lt;/mi>&lt;mi>s&lt;/mi>&lt;mi>u&lt;/mi>&lt;mi>l&lt;/mi>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo>=&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;msub>&lt;mi>C&lt;/mi>&lt;mrow>&lt;mi>s&lt;/mi>&lt;mi>r&lt;/mi>&lt;mi>c&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo>∗&lt;/mo>&lt;msub>&lt;mi>F&lt;/mi>&lt;mrow>&lt;mi>s&lt;/mi>&lt;mi>r&lt;/mi>&lt;mi>c&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo stretchy="false">)&lt;/mo>&lt;mo>+&lt;/mo>&lt;mo stretchy="false">(&lt;/mo>&lt;msub>&lt;mi>C&lt;/mi>&lt;mrow>&lt;mi>d&lt;/mi>&lt;mi>e&lt;/mi>&lt;mi>s&lt;/mi>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo>∗&lt;/mo>&lt;msub>&lt;mi>F&lt;/mi>&lt;mrow>&lt;mi>d&lt;/mi>&lt;mi>e&lt;/mi>&lt;mi>s&lt;/mi>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">C_{result} = (C_{src} * F_{src}) + (C_{dest} * F_{dest})&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 
 &lt;/div>
&lt;ul>
&lt;li>&lt;mark>(Source Color)&lt;/mark>：即将画上去的颜色（来自 Fragment Shader）。&lt;/li>
&lt;li>&lt;mark>(Source Factor)&lt;/mark>：源颜色的权重。&lt;/li>
&lt;li>&lt;mark>(Destination Color)&lt;/mark>：已经在颜色缓冲区里的颜色（背景色）。&lt;/li>
&lt;li>&lt;mark>(Destination Factor)&lt;/mark>：目标颜色的权重。&lt;/li>
&lt;/ul>
&lt;h1 id="最常用的配置实现透明效果">最常用的配置：实现透明效果&lt;a class="anchor" href="#%e6%9c%80%e5%b8%b8%e7%94%a8%e7%9a%84%e9%85%8d%e7%bd%ae%e5%ae%9e%e7%8e%b0%e9%80%8f%e6%98%8e%e6%95%88%e6%9e%9c">#&lt;/a>&lt;/h1>
&lt;p>为了实现自然的透明（即：新物体的透明度越高，透出的背景越多），Cherno 给出了最经典的配置方案：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scss" data-lang="scss">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">GLCall&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#f92672">glBlendFunc&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#f92672">GL_SRC_ALPHA&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">GL_ONE_MINUS_SRC_ALPHA&lt;/span>&lt;span style="color:#f92672">))&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">//&lt;/span>&lt;span style="color:#f92672">函数glBlendFunc第一个参数默认值为&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">：&lt;/span>&lt;span style="color:#f92672">GL_ONE&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">，&lt;/span>&lt;span style="color:#f92672">第二个参数默认值为&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">：&lt;/span>&lt;span style="color:#f92672">GL_ZERO&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;mark>逻辑拆解：&lt;/mark>&lt;/p>
&lt;ol>
&lt;li>
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msub>&lt;mi>F&lt;/mi>&lt;mrow>&lt;mi>s&lt;/mi>&lt;mi>r&lt;/mi>&lt;mi>c&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo>=&lt;/mo>&lt;mi>G&lt;/mi>&lt;mi>L&lt;/mi>&lt;mi mathvariant="normal">_&lt;/mi>&lt;mi>S&lt;/mi>&lt;mi>R&lt;/mi>&lt;mi>C&lt;/mi>&lt;mi mathvariant="normal">_&lt;/mi>&lt;mi>A&lt;/mi>&lt;mi>L&lt;/mi>&lt;mi>P&lt;/mi>&lt;mi>H&lt;/mi>&lt;mi>A&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">F_{src} = GL\_SRC\_ALPHA&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 源颜色的权重是它自己的 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>A&lt;/mi>&lt;mi>l&lt;/mi>&lt;mi>p&lt;/mi>&lt;mi>h&lt;/mi>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">Alpha&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 值。&lt;/li>
&lt;li>
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;msub>&lt;mi>F&lt;/mi>&lt;mrow>&lt;mi>d&lt;/mi>&lt;mi>e&lt;/mi>&lt;mi>s&lt;/mi>&lt;mi>t&lt;/mi>&lt;/mrow>&lt;/msub>&lt;mo>=&lt;/mo>&lt;mi>G&lt;/mi>&lt;mi>L&lt;/mi>&lt;mi mathvariant="normal">_&lt;/mi>&lt;mi>O&lt;/mi>&lt;mi>N&lt;/mi>&lt;mi>E&lt;/mi>&lt;mi mathvariant="normal">_&lt;/mi>&lt;mi>M&lt;/mi>&lt;mi>I&lt;/mi>&lt;mi>N&lt;/mi>&lt;mi>U&lt;/mi>&lt;mi>S&lt;/mi>&lt;mi mathvariant="normal">_&lt;/mi>&lt;mi>S&lt;/mi>&lt;mi>R&lt;/mi>&lt;mi>C&lt;/mi>&lt;mi mathvariant="normal">_&lt;/mi>&lt;mi>A&lt;/mi>&lt;mi>L&lt;/mi>&lt;mi>P&lt;/mi>&lt;mi>H&lt;/mi>&lt;mi>A&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">F_{dest} = GL\_ONE\_MINUS\_SRC\_ALPHA&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 背景颜色的权重是 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>1&lt;/mn>&lt;mo>−&lt;/mo>&lt;mi>A&lt;/mi>&lt;mi>l&lt;/mi>&lt;mi>p&lt;/mi>&lt;mi>h&lt;/mi>&lt;mi>a&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">1 - Alpha&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 。&lt;/li>
&lt;/ol>
&lt;p>&lt;mark>举个例子：&lt;/mark> 如果你画一个 Alpha 为 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0.3&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0.3&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 （ 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>30&lt;/mn>&lt;mi mathvariant="normal">%&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">30\%&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 不透明）的红色方块在黑色背景上：&lt;/p></description></item><item><title>17关于纹理</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/17%E5%85%B3%E4%BA%8E%E7%BA%B9%E7%90%86/</link><pubDate>Sun, 29 Mar 2026 23:43:31 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/17%E5%85%B3%E4%BA%8E%E7%BA%B9%E7%90%86/</guid><description>&lt;p>第 17 集是 OpenGL 系列中视觉效果实现飞跃的一集。在此之前，你只能画出单色的三角形；学完纹理后，你就能把&lt;mark>图片&lt;/mark>贴在你的几何图形上。&lt;/p>
&lt;p>即便你现在还不学习具体的 API，了解其背后的“映射逻辑”对你理解未来的 3D 渲染至关重要。&lt;/p>
&lt;h1 id="简述">简述&lt;a class="anchor" href="#%e7%ae%80%e8%bf%b0">#&lt;/a>&lt;/h1>
&lt;h2 id="纹理的基本原理坐标映射">纹理的基本原理：坐标映射&lt;a class="anchor" href="#%e7%ba%b9%e7%90%86%e7%9a%84%e5%9f%ba%e6%9c%ac%e5%8e%9f%e7%90%86%e5%9d%90%e6%a0%87%e6%98%a0%e5%b0%84">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>核心概念&lt;/mark>：纹理坐标（UV 坐标）。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>UV 坐标系&lt;/mark>：&lt;/p>
&lt;ul>
&lt;li>它是归一化的，
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>u&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">u&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 和 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mi>v&lt;/mi>&lt;/mrow>&lt;annotation encoding="application/x-tex">v&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 的范围都是 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>0.0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">0.0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 到 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>1.0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">1.0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 。&lt;/li>
&lt;li>左下角是 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">(&lt;/mo>&lt;mn>0&lt;/mn>&lt;mo separator="true">,&lt;/mo>&lt;mn>0&lt;/mn>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">(0, 0)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 ，右上角是 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo stretchy="false">(&lt;/mo>&lt;mn>1&lt;/mn>&lt;mo separator="true">,&lt;/mo>&lt;mn>1&lt;/mn>&lt;mo stretchy="false">)&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">(1, 1)&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>映射逻辑&lt;/mark>：你在顶点数据中多加两个 float（），告诉 GPU：“这个顶点对应图片上的哪个点”。GPU 会自动在顶点之间进行插值，算出中间每个像素该涂什么颜色。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="图像加载与-stb_image">图像加载与 stb_image&lt;a class="anchor" href="#%e5%9b%be%e5%83%8f%e5%8a%a0%e8%bd%bd%e4%b8%8e-stb_image">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>痛点&lt;/mark>：OpenGL 本身不认识 &lt;code>.png&lt;/code> 或 &lt;code>.jpg&lt;/code> 这种压缩格式。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>解决方案&lt;/mark>：引入一个极简的开源库 &lt;mark>&lt;code>stb_image&lt;/code>&lt;/mark>。&lt;/p>
&lt;ul>
&lt;li>这是一个单头文件库，非常符合 Cherno 的极简风格。&lt;/li>
&lt;li>它的作用是&lt;mark>将磁盘上的图片文件解码成内存中的 RGBA 字节数组（即一串 &lt;code>unsigned char&lt;/code>）&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="opengl-纹理对象-texture-object">OpenGL 纹理对象 (Texture Object)&lt;a class="anchor" href="#opengl-%e7%ba%b9%e7%90%86%e5%af%b9%e8%b1%a1-texture-object">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>创建与绑定&lt;/mark>：&lt;/p>
&lt;ul>
&lt;li>类似于 &lt;code>VertexBuffer&lt;/code>，你需要 &lt;code>glGenTextures&lt;/code> 生成一个 ID，然后 &lt;code>glBindTexture&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>关键参数设置 (Parameters)&lt;/mark>：&lt;/p>
&lt;ul>
&lt;li>&lt;mark>过滤 (Filtering)&lt;/mark>：当图片被放大或缩小时，像素该怎么补全？（&lt;code>GL_LINEAR&lt;/code> 线性平滑，或 &lt;code>GL_NEAREST&lt;/code> 像素风）。&lt;/li>
&lt;li>&lt;mark>包装 (Wrapping)&lt;/mark>：当 UV 坐标超过 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mn>1.0&lt;/mn>&lt;/mrow>&lt;annotation encoding="application/x-tex">1.0&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 时，图片是重复（Repeat）还是拉伸（Clamp）？&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>数据上传&lt;/mark>：使用 &lt;code>glTexImage2D&lt;/code> 将 CPU 内存中的像素数组发送到 GPU 显存。&lt;/p></description></item><item><title>13-16抽象OpenGL成类</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/13-16%E6%8A%BD%E8%B1%A1OpenGL%E6%88%90%E7%B1%BB/</link><pubDate>Wed, 25 Mar 2026 18:01:15 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/13-16%E6%8A%BD%E8%B1%A1OpenGL%E6%88%90%E7%B1%BB/</guid><description>&lt;p>将零散的 OpenGL 原生 API 封装成 &lt;mark>C++ 类&lt;/mark>。这不仅是为了让 &lt;code>main&lt;/code> 函数变干净，更是为了构建一个可复用的&lt;mark>渲染引擎底层&lt;/mark>。&lt;/p>
&lt;h1 id="13-16抽象opengl成类">13-16抽象OpenGL成类&lt;a class="anchor" href="#13-16%e6%8a%bd%e8%b1%a1opengl%e6%88%90%e7%b1%bb">#&lt;/a>&lt;/h1>
&lt;h2 id="为什么要抽象工程思维">为什么要抽象？（工程思维）&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e6%8a%bd%e8%b1%a1%e5%b7%a5%e7%a8%8b%e6%80%9d%e7%bb%b4">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>现状&lt;/mark>：&lt;code>main.cpp&lt;/code> 已经膨胀到几百行，充斥着大量的 &lt;code>glGen&lt;/code>、&lt;code>glBind&lt;/code>。&lt;/li>
&lt;li>&lt;mark>目标&lt;/mark>：我们不希望在业务逻辑里看到底层的 &lt;code>unsigned int ID&lt;/code>。我们要操作的是“对象”（Object）。&lt;/li>
&lt;li>&lt;mark>类划分预想&lt;/mark>：
&lt;ul>
&lt;li>&lt;mark>VertexBuffer&lt;/mark>：管理 &lt;code>GL_ARRAY_BUFFER&lt;/code>。&lt;/li>
&lt;li>&lt;mark>IndexBuffer&lt;/mark>：管理 &lt;code>GL_ELEMENT_ARRAY_BUFFER&lt;/code>。&lt;/li>
&lt;li>&lt;mark>VertexArray&lt;/mark>：管理属性布局（Layout）和 VAO。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="封装-vertexbuffer-类">封装 VertexBuffer 类&lt;a class="anchor" href="#%e5%b0%81%e8%a3%85-vertexbuffer-%e7%b1%bb">#&lt;/a>&lt;/h2>
&lt;p>这是最基础的一步。将 VBO 的创建、绑定和销毁封装起来。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>构造函数&lt;/mark>：接收数据和大小，直接 &lt;code>glGen&lt;/code> 并 &lt;code>glBufferData&lt;/code>。&lt;/li>
&lt;li>&lt;mark>析构函数&lt;/mark>：调用 &lt;code>glDeleteBuffers&lt;/code>，实现 &lt;mark>RAII&lt;/mark>（资源获取即初始化）机制，防止内存泄漏。&lt;/li>
&lt;li>&lt;mark>关键方法&lt;/mark>：&lt;code>Bind()&lt;/code> 和 &lt;code>Unbind()&lt;/code>。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 你的博客可以展示这个极简结构
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">VertexBuffer&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_RendererID; &lt;span style="color:#75715e">// Cherno 喜欢用 m_ 前缀表示成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> VertexBuffer(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> data, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">~&lt;/span>VertexBuffer();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Bind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Unbind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="封装-indexbuffer-类">封装 IndexBuffer 类&lt;a class="anchor" href="#%e5%b0%81%e8%a3%85-indexbuffer-%e7%b1%bb">#&lt;/a>&lt;/h2>
&lt;p>与 VertexBuffer 几乎一模一样，但有两点不同：&lt;/p>
&lt;ol>
&lt;li>&lt;mark>目标类型&lt;/mark>：固定为 &lt;code>GL_ELEMENT_ARRAY_BUFFER&lt;/code>。&lt;/li>
&lt;li>&lt;mark>计数器&lt;/mark>：增加一个 &lt;code>m_Count&lt;/code> 变量，记录有多少个索引（Indices），因为 &lt;code>glDrawElements&lt;/code> 绘图时需要这个数字。&lt;/li>
&lt;/ol>
&lt;h1 id="代码">代码&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;h2 id="render-渲染器">Render 渲染器&lt;a class="anchor" href="#render-%e6%b8%b2%e6%9f%93%e5%99%a8">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Renderer.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//编译器第一次遇到这个文件，正常读取内容。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//编译器会记下这个文件的物理路径。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//当后续代码再次尝试 #include 这个路径的文件时，编译器直接跳过，不再读取。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;GL/glew.h&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexArray.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;IndexBuffer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Shader.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//_debugbreak() 是msvc特有的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//__FILE__和__LINE__ 是所有编译器都支持的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//#x：字符串化操作符。它会将你传入的代码直接转成字符串
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//__FILE__ 和 __LINE__：编译器内置宏，自动获取当前代码所在的文件名和行号
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#define ASSERT(x) if(!(x)) __debugbreak();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#define GLCall(x) GLClearError();\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	x;\
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	ASSERT(GLLogCall(#x,__FILE__,__LINE__));
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">GLClearError&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#a6e22e">GLLogCall&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> function,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> file, &lt;span style="color:#66d9ef">int&lt;/span> line);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Renderer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Clear() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Draw&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> VertexArray&lt;span style="color:#f92672">&amp;amp;&lt;/span> va, &lt;span style="color:#66d9ef">const&lt;/span> IndexBuffer&lt;span style="color:#f92672">&amp;amp;&lt;/span> ib, &lt;span style="color:#66d9ef">const&lt;/span> Shader&lt;span style="color:#f92672">&amp;amp;&lt;/span> shader) &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Renderer.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Renderer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">GLClearError&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//直到不是GL_NO_ERROR，就退出while循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">while&lt;/span> (glGetError() &lt;span style="color:#f92672">!=&lt;/span> GL_NO_ERROR);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#a6e22e">GLLogCall&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> function,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> file, &lt;span style="color:#66d9ef">int&lt;/span> line)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">while&lt;/span> (GLenum error &lt;span style="color:#f92672">=&lt;/span> glGetError())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[OpenGL Error](&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> error &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;): &amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> function &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> file &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> line &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> true;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Renderer&lt;span style="color:#f92672">::&lt;/span>Clear() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	GLCall(glClear(GL_COLOR_BUFFER_BIT));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Renderer&lt;span style="color:#f92672">::&lt;/span>Draw(&lt;span style="color:#66d9ef">const&lt;/span> VertexArray&lt;span style="color:#f92672">&amp;amp;&lt;/span> va, &lt;span style="color:#66d9ef">const&lt;/span> IndexBuffer&lt;span style="color:#f92672">&amp;amp;&lt;/span> ib, &lt;span style="color:#66d9ef">const&lt;/span> Shader&lt;span style="color:#f92672">&amp;amp;&lt;/span> shader) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//绘图前重新绑定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	shader.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//必须先绑定program，因为vao不负责着色器程序的切换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	va.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这个可以不用，已经在va中录制了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//ib.Bind();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	GLCall(glDrawElements(GL_TRIANGLES, ib.GetCount(), GL_UNSIGNED_INT, &lt;span style="color:#66d9ef">nullptr&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//绘制后经常不需要再解绑，因为这会消耗性能，而且
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//我们经常会在下一帧继续使用它们并覆盖 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="vertextbuffer-顶点缓冲区">VertextBuffer 顶点缓冲区&lt;a class="anchor" href="#vertextbuffer-%e9%a1%b6%e7%82%b9%e7%bc%93%e5%86%b2%e5%8c%ba">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//VertextBuffer.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//专门处理顶点缓冲区的生成、绑定、解绑及内存释放
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">VertexBuffer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//一个相关的渲染器id
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_RendererID;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//size：大小
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	VertexBuffer(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> data, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>VertexBuffer();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Bind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Unbind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//VertexBuffer.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexBuffer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Render.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VertexBuffer&lt;span style="color:#f92672">::&lt;/span>VertexBuffer(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> data, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 生成一个缓冲区 ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glGenBuffers(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到顶点缓冲区插槽
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 将顶点数据从 CPU 内存拷贝到 GPU 显存，设为静态读取模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBufferData(GL_ARRAY_BUFFER, size,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		data, GL_STATIC_DRAW));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VertexBuffer&lt;span style="color:#f92672">::~&lt;/span>VertexBuffer()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	GLCall(glDeleteBuffers(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> VertexBuffer&lt;span style="color:#f92672">::&lt;/span>Bind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到顶点缓冲区插槽
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBindBuffer(GL_ARRAY_BUFFER, m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> VertexBuffer&lt;span style="color:#f92672">::&lt;/span>Unbind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到顶点缓冲区插槽
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBindBuffer(GL_ARRAY_BUFFER, &lt;span style="color:#ae81ff">0&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="indexbuffer-索引缓冲区">IndexBuffer 索引缓冲区&lt;a class="anchor" href="#indexbuffer-%e7%b4%a2%e5%bc%95%e7%bc%93%e5%86%b2%e5%8c%ba">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//IndexBuffer.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//专门处理索引缓冲区的生成、绑定、解绑及内存释放
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//索引缓冲区：可以用来只绘制某个面（如果顶点缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//包括了很多顶点的话）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">IndexBuffer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//一个相关的渲染器id
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_RendererID;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_Count;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//count：个数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	IndexBuffer(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> data, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> count);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>IndexBuffer();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Bind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Unbind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">inline&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetCount&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Count; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//IndexBuffer.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;IndexBuffer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Render.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>IndexBuffer&lt;span style="color:#f92672">::&lt;/span>IndexBuffer(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> data, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> count)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">:&lt;/span>m_Count(count)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ASSERT(&lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>) &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(GLuint));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 生成一个缓冲区 ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glGenBuffers(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到元素数组缓冲区 (Element Array Buffer)插槽，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//也称索引缓冲区对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 将顶点数据从 CPU 内存拷贝到 GPU 显存，设为静态读取模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBufferData(GL_ELEMENT_ARRAY_BUFFER, count &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		data, GL_STATIC_DRAW));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>IndexBuffer&lt;span style="color:#f92672">::~&lt;/span>IndexBuffer()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	GLCall(glDeleteBuffers(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> IndexBuffer&lt;span style="color:#f92672">::&lt;/span>Bind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到元素数组缓冲区插槽
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_RendererID));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> IndexBuffer&lt;span style="color:#f92672">::&lt;/span>Unbind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到元素数组缓冲区插槽
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLCall(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, &lt;span style="color:#ae81ff">0&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="vertexbufferlayout-顶点缓冲区布局设置">VertexBufferLayout 顶点缓冲区布局设置&lt;a class="anchor" href="#vertexbufferlayout-%e9%a1%b6%e7%82%b9%e7%bc%93%e5%86%b2%e5%8c%ba%e5%b8%83%e5%b1%80%e8%ae%be%e7%bd%ae">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//VertexBufferLayout.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;GL/glew.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Renderer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">VertexBufferElement&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> type;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> count;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span> normalized;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetSizeOfType&lt;/span>(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> type)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">switch&lt;/span> (type)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">case&lt;/span> GL_FLOAT: &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">case&lt;/span> GL_UNSIGNED_INT: &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">case&lt;/span> GL_UNSIGNED_BYTE: &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		ASSERT(false);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">VertexBufferLayout&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>VertexBufferElement&lt;span style="color:#f92672">&amp;gt;&lt;/span> m_Elements;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_Stride;&lt;span style="color:#75715e">//步长
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">public&lt;/span> &lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	VertexBufferLayout()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Stride(&lt;span style="color:#ae81ff">0&lt;/span>) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//解释一下，第n个push的就是第n组属性的布局
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Push(&lt;span style="color:#66d9ef">int&lt;/span> cout)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">static_assert&lt;/span>(false);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//位置 ($x, y, z$)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Push&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">float&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> count)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Elements.push_back({ GL_FLOAT,count,GL_FALSE });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Stride &lt;span style="color:#f92672">+=&lt;/span> count &lt;span style="color:#f92672">*&lt;/span> VertexBufferElement&lt;span style="color:#f92672">::&lt;/span>GetSizeOfType(GL_FLOAT);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//ID、索引
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Push&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> count)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Elements.push_back({ GL_UNSIGNED_INT,count,GL_FALSE });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Stride &lt;span style="color:#f92672">+=&lt;/span> count &lt;span style="color:#f92672">*&lt;/span> VertexBufferElement&lt;span style="color:#f92672">::&lt;/span>GetSizeOfType(GL_UNSIGNED_INT);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//颜色 (R, G, B, A)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果你设置 GL_TRUE (归一化)：OpenGL 会自动帮你做除法。比如你传 255，Shader 拿到的是 $255 / 255 = 1.0$；你传 128，Shader 拿到的是 $0.5$
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Push&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> count)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Elements.push_back({ GL_UNSIGNED_BYTE,count,GL_TRUE });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Stride &lt;span style="color:#f92672">+=&lt;/span> count &lt;span style="color:#f92672">*&lt;/span> VertexBufferElement&lt;span style="color:#f92672">::&lt;/span>GetSizeOfType(GL_UNSIGNED_BYTE);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">inline&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>VertexBufferElement&lt;span style="color:#f92672">&amp;gt;&lt;/span> GetElements() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Elements; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">inline&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetStrde&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Stride; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="vertexarray-顶点数组属性绑定">VertexArray 顶点数组（属性）绑定&lt;a class="anchor" href="#vertexarray-%e9%a1%b6%e7%82%b9%e6%95%b0%e7%bb%84%e5%b1%9e%e6%80%a7%e7%bb%91%e5%ae%9a">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//VertexArray.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexBuffer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//#include &amp;#34;VertexBufferLayout.h&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//它告诉编译器：“哥们，后面会有一个类叫 VertexBufferLayout，我现在先提一嘴，你先别管它长啥样，只要知道它是个‘类’就行。”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">VertexBufferLayout&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">VertexArray&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_RendererID;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	VertexArray();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>VertexArray();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">AddBuffer&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> VertexBuffer&lt;span style="color:#f92672">&amp;amp;&lt;/span> vb, &lt;span style="color:#66d9ef">const&lt;/span> VertexBufferLayout&lt;span style="color:#f92672">&amp;amp;&lt;/span> layout);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Bind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Unbind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//VertexArray.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexArray.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//这里要真正调用 layout.GetElements()。这时候编译器必须看到具体的类定义，才能知道 GetElements() 函数长什么样。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexBufferLayout.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VertexArray&lt;span style="color:#f92672">::&lt;/span>VertexArray()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glGenVertexArrays(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>m_RendererID);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>VertexArray&lt;span style="color:#f92672">::~&lt;/span>VertexArray()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glDeleteVertexArrays(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>m_RendererID);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> VertexArray&lt;span style="color:#f92672">::&lt;/span>AddBuffer(&lt;span style="color:#66d9ef">const&lt;/span> VertexBuffer&lt;span style="color:#f92672">&amp;amp;&lt;/span> vb, &lt;span style="color:#66d9ef">const&lt;/span> VertexBufferLayout&lt;span style="color:#f92672">&amp;amp;&lt;/span> layout)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vb.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> elements &lt;span style="color:#f92672">=&lt;/span> layout.GetElements();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> offset &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> i&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>;i&lt;span style="color:#f92672">&amp;lt;&lt;/span>elements.size();i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> element &lt;span style="color:#f92672">=&lt;/span> elements[i];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 启用索引为 i 的(顶点)属性 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glEnableVertexAttribArray(i);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 打标签：它把当前 GL_ARRAY_BUFFER 里的数据流，贴上了“i号”的标签。2. 定规则：它告诉 GPU，当你（Shader）想要 location = 0 的数据时，请按照“每 count 个 float 为一组”的规则去缓存里抓取。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glVertexAttribPointer(i, element.count, element.type, element.normalized, layout.GetStrde(), (&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)offset);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		offset &lt;span style="color:#f92672">+=&lt;/span> element.count &lt;span style="color:#f92672">*&lt;/span> VertexBufferElement&lt;span style="color:#f92672">::&lt;/span>GetSizeOfType(element.type);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> VertexArray&lt;span style="color:#f92672">::&lt;/span>Bind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glBindVertexArray(m_RendererID);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> VertexArray&lt;span style="color:#f92672">::&lt;/span>Unbind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glBindVertexArray(&lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里是否要禁用呢，但是视频里面没有存count，所以也不知道总共有几个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">/*for (unsigned int i = 0; i &amp;lt; elements.size(); i++)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">		glDisableVertexAttribArray(i);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	}*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="shader着色器">Shader着色器&lt;a class="anchor" href="#shader%e7%9d%80%e8%89%b2%e5%99%a8">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Shader.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;unordered_map&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">ShaderProgramSource&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string VertexSource;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string FragmentSource;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Shader&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string m_FilePath;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_RendererID;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>unordered_map&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> m_UniformLocationCache;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// caching for uniforms
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Shader(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filepath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Shader();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Bind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Unbind&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">SetUniform4f&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name, &lt;span style="color:#66d9ef">float&lt;/span> v0, &lt;span style="color:#66d9ef">float&lt;/span> v1,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">float&lt;/span> v2, &lt;span style="color:#66d9ef">float&lt;/span> v3);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">bool&lt;/span> CompileShader();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetUniformLocation&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ShaderProgramSource &lt;span style="color:#a6e22e">ParseShader&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filepath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">CompileShader&lt;/span>(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> type,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> source);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建着色器程序对象：编译并链接顶点着色器和片段着色器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">CreateShader&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertexShader,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> fragmentShader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Shader.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Shader.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;fstream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;sstream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Render.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Shader&lt;span style="color:#f92672">::&lt;/span>Shader(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filepath)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">:&lt;/span>m_FilePath(filepath),m_RendererID(&lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ShaderProgramSource source &lt;span style="color:#f92672">=&lt;/span> ParseShader(filepath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_RendererID &lt;span style="color:#f92672">=&lt;/span> CreateShader(source.VertexSource, source.FragmentSource);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Shader&lt;span style="color:#f92672">::~&lt;/span>Shader()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glDeleteProgram(m_RendererID);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Shader&lt;span style="color:#f92672">::&lt;/span>Bind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glUseProgram(m_RendererID);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Shader&lt;span style="color:#f92672">::&lt;/span>Unbind() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		glUseProgram(&lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> ShaderProgramSource Shader&lt;span style="color:#f92672">::&lt;/span>ParseShader(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filepath)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ShaderType&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		NONE &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>, VERTEX &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>, FRAGMENT &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//input file stream
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>ifstream stream(filepath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string line;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>stringstream ss[&lt;span style="color:#ae81ff">2&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ShaderType type &lt;span style="color:#f92672">=&lt;/span> ShaderType&lt;span style="color:#f92672">::&lt;/span>NONE;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">while&lt;/span> (getline(stream, line))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (line.find(&lt;span style="color:#e6db74">&amp;#34;#shader&amp;#34;&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">::&lt;/span>npos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">if&lt;/span> (line.find(&lt;span style="color:#e6db74">&amp;#34;vertex&amp;#34;&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">::&lt;/span>npos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				type &lt;span style="color:#f92672">=&lt;/span> ShaderType&lt;span style="color:#f92672">::&lt;/span>VERTEX;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#a6e22e">if&lt;/span> (line.find(&lt;span style="color:#e6db74">&amp;#34;fragment&amp;#34;&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">::&lt;/span>npos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				type &lt;span style="color:#f92672">=&lt;/span> ShaderType&lt;span style="color:#f92672">::&lt;/span>FRAGMENT;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			ss[(&lt;span style="color:#66d9ef">int&lt;/span>)type] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> line &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> { ss[&lt;span style="color:#ae81ff">0&lt;/span>].str(),ss[&lt;span style="color:#ae81ff">1&lt;/span>].str() };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//GLenum也就是unsigned int,这里不用GLenum是为了解耦
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> Shader&lt;span style="color:#f92672">::&lt;/span>CompileShader(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> type,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> source)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建着色器对象，向 OpenGL 申请一个空的“容器”来存放你的代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//把光标放在 glCreateShader( 的左括号后面，然后按下 Ctrl + Shift + Space。会弹出一个小黑框，显示：GLuint glCreateShader(GLenum type)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//到glew.h搜索，发现typedef unsigned int GLenum;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> id &lt;span style="color:#f92672">=&lt;/span> glCreateShader(type);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//返回一个指向该字符串首地址的只读指针（const char*）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> src &lt;span style="color:#f92672">=&lt;/span> source.c_str();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//有了容器后，你需要把写好的字符串代码塞进去（拷贝）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3种用法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//1. glShaderSource(id, 1, &amp;amp;src, nullptr);	只有一个字符串，且它是以 \0 结尾的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. glShaderSource(id, 1, &amp;amp;src, &amp;amp;len);	只有一个字符串，长度由 len 指定。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3. glShaderSource(id, 2, strings, lengths);	有两个字符串片段（数组形式），长度分别由 lengths[0] 和 lengths[1] 指定。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glShaderSource(id, &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>src, &lt;span style="color:#66d9ef">nullptr&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//将你的 GLSL 代码翻译成显卡能理解的机器指令
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glCompileShader(id);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//错误处理
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 查询编译状态：询问 OpenGL 这个 shader 编译成功了吗？
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// GL_COMPILE_STATUS 会把结果存入 result 中（成功为 GL_TRUE，失败为 GL_FALSE）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glGetShaderiv(id, GL_COMPILE_STATUS, &lt;span style="color:#f92672">&amp;amp;&lt;/span>result);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (result &lt;span style="color:#f92672">==&lt;/span> GL_FALSE)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">int&lt;/span> length;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//获取错误日志长度：如果编译失败，先问一下错误信息一共有多少个字符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glGetShaderiv(id, GL_INFO_LOG_LENGTH, &lt;span style="color:#f92672">&amp;amp;&lt;/span>length);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在栈上申请内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//如果申请的内存太大，alloca会导致栈溢出（1MB）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)alloca(length &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">char&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//提取错误信息：把显卡驱动里的具体报错文字拷贝到我们刚才申请的 message 内存中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glGetShaderInfoLog(id, length, &lt;span style="color:#f92672">&amp;amp;&lt;/span>length, message);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Failed to compile &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> ((type &lt;span style="color:#f92672">==&lt;/span> GL_VERTEX_SHADER) &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#e6db74">&amp;#34;vertex&amp;#34;&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;fragment&amp;#34;&lt;/span>) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; shader!&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//清理：编译失败了，这个 shader 对象也就没用了，删掉它防止内存泄漏
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glDeleteShader(id);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> id;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> Shader&lt;span style="color:#f92672">::&lt;/span>CreateShader(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertexShader,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> fragmentShader)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在 GPU 中申请一个空的“程序对象”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> program &lt;span style="color:#f92672">=&lt;/span> glCreateProgram();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译顶点着色器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> vs &lt;span style="color:#f92672">=&lt;/span> CompileShader(GL_VERTEX_SHADER,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		vertexShader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译片段着色器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> fs &lt;span style="color:#f92672">=&lt;/span> CompileShader(GL_FRAGMENT_SHADER,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		fragmentShader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//把已经编译好的顶点着色器和片段着色器附加到程序对象中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glAttachShader(program, vs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glAttachShader(program, fs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//链接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glLinkProgram(program);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//验证当前的程序是否能在当前的 OpenGL 状态下执行（
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 检查顶点着色器的输出是否与片段着色器的输入匹配，并
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 生成最终的可执行二进制代码。）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glValidateProgram(program);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//删除临时的中间产物（类似编译完 C++ 后删除 .obj
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glDeleteShader(vs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glDeleteShader(fs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> program;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Shader&lt;span style="color:#f92672">::&lt;/span>SetUniform4f(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name, &lt;span style="color:#66d9ef">float&lt;/span> v0, &lt;span style="color:#66d9ef">float&lt;/span> v1, &lt;span style="color:#66d9ef">float&lt;/span> v2, &lt;span style="color:#66d9ef">float&lt;/span> v3)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glUniform4f(GetUniformLocation(name), v0, v1, v2, v3);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> Shader&lt;span style="color:#f92672">::&lt;/span>GetUniformLocation(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (m_UniformLocationCache.find(name) &lt;span style="color:#f92672">!=&lt;/span> m_UniformLocationCache.end())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_UniformLocationCache[name];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> location&lt;span style="color:#f92672">=&lt;/span>glGetUniformLocation(m_RendererID, name.c_str());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (location &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Warning: uniform &amp;#39;&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> name &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&amp;#39; doesn&amp;#39;t exist!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_UniformLocationCache[name] &lt;span style="color:#f92672">=&lt;/span> location;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> location;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="main-主文件">Main 主文件&lt;a class="anchor" href="#main-%e4%b8%bb%e6%96%87%e4%bb%b6">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Main.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#ifdef LY_EP16
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;GL/glew.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;GLFW/glfw3.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;fstream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;sstream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Renderer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexBuffer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexBufferLayout.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;IndexBuffer.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;VertexArray.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Shader.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>(&lt;span style="color:#66d9ef">void&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#pragma region 一些初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		GLFWwindow&lt;span style="color:#f92672">*&lt;/span> window;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 初始化 GLFW 库，失败则退出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>glfwInit())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//强制指定使用 Core Profile（核心模式），如果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//没有手动写着色器则不会渲染；如果不是核心模式，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//在固定管线中默认颜色是白色，且默认顶点在NDC标准
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//设备坐标系中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//这是兼容配置模式,会让VAO0成为默认对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, &lt;span style="color:#ae81ff">3&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, &lt;span style="color:#ae81ff">3&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 创建窗口对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		window &lt;span style="color:#f92672">=&lt;/span> glfwCreateWindow(&lt;span style="color:#ae81ff">640&lt;/span>, &lt;span style="color:#ae81ff">480&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>, NULL, NULL);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>window)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 创建失败则清理并退出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glfwTerminate();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 将当前窗口的上下文设置为 OpenGL 渲染的目标
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwMakeContextCurrent(window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		glfwSwapInterval(&lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 初始化 GLEW 以加载 OpenGL 函数指针，需在有上下文后执行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (glewInit() &lt;span style="color:#f92672">!=&lt;/span> GLEW_OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Error!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#pragma endregion
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 定义三角形的顶点坐标（CPU 内存）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">float&lt;/span> positions[] &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>,&lt;span style="color:#75715e">//0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>,&lt;span style="color:#75715e">//1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">0.5f&lt;/span>,&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//0.5f, 0.5f,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">0.5f&lt;/span>,&lt;span style="color:#75715e">//3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//-0.5f, -0.5f,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> indices[] &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#ae81ff">0&lt;/span>,&lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span>,&lt;span style="color:#ae81ff">0&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		VertexArray va;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//申请创建一个GPU上的缓冲区，绑定并复制进去数据构造函
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//数中已经绑定了，这样glVertexAttribPointer才有效果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		VertexBuffer vb(positions, &lt;span style="color:#ae81ff">4&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		VertexBufferLayout layout;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		layout.Push&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">float&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		va.AddBuffer(vb, layout);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//申请创建一个GPU上的缓冲区，绑定并复制进去数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		IndexBuffer ib(indices, &lt;span style="color:#ae81ff">6&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Shader shader(&lt;span style="color:#e6db74">&amp;#34;res/shaders/Basic.shader&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		shader.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		shader.SetUniform4f(&lt;span style="color:#e6db74">&amp;#34;u_Color&amp;#34;&lt;/span>, &lt;span style="color:#ae81ff">0.8f&lt;/span>, &lt;span style="color:#ae81ff">0.3f&lt;/span>, &lt;span style="color:#ae81ff">0.8f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//===这里故意把他解绑了（假设他去绑定别的去了）===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		vb.Unbind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		shader.Unbind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		va.Unbind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//element_array_buffer 和vertexAttribArray不能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//在解绑vao之前处理，否则就记录进去了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ib.Unbind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//========================================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">float&lt;/span> r &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">float&lt;/span> increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Renderer renderer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 游戏/渲染主循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">while&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>glfwWindowShouldClose(window))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 清理屏幕颜色缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			renderer.Clear();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//必须先绑定program，因为vao不负责着色器程序的切换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//va.Bind();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">if&lt;/span> (r &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">1.0f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (r &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				increment &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.05f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			r &lt;span style="color:#f92672">+=&lt;/span> increment;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//绘图前重新绑定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			shader.Bind();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//在u_Color的位置上设置数值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			shader.SetUniform4f(&lt;span style="color:#e6db74">&amp;#34;u_Color&amp;#34;&lt;/span>, r, &lt;span style="color:#ae81ff">0.3f&lt;/span>, &lt;span style="color:#ae81ff">0.0f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//========设置uniform========
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			renderer.Draw(va, ib, shader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 交换前后缓冲区以刷新画面
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glfwSwapBuffers(window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 轮询并处理窗口事件（如键盘输入、关闭动作）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			glfwPollEvents();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//最后解绑vao
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//glBindVertexArray(0);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 退出前清理资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//glfwTerminate会破坏Context，导致析构函数中的glGetError()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//返回一个OpenGL错误
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glfwTerminate();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>12顶点数组</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/12%E9%A1%B6%E7%82%B9%E6%95%B0%E7%BB%84/</link><pubDate>Wed, 25 Mar 2026 13:30:24 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/12%E9%A1%B6%E7%82%B9%E6%95%B0%E7%BB%84/</guid><description>&lt;p>第 12 集是整个系列中非常关键的&lt;mark>架构转折点&lt;/mark>。Cherno 在这一集深入讲解了 &lt;mark>Vertex Array Object (VAO)&lt;/mark>。&lt;/p>
&lt;p>如果你之前觉得代码里那堆 &lt;code>glVertexAttribPointer&lt;/code> 既乱又难记，那么这一集就是为你准备的“整理收纳柜”。&lt;/p>
&lt;h1 id="总述">总述&lt;a class="anchor" href="#%e6%80%bb%e8%bf%b0">#&lt;/a>&lt;/h1>
&lt;h2 id="为什么要用-vao痛点分析">为什么要用 VAO？（痛点分析）&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e7%94%a8-vao%e7%97%9b%e7%82%b9%e5%88%86%e6%9e%90">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>现状&lt;/mark>：在核心模式（Core Profile）下，OpenGL 要求必须绑定一个 VAO 才能绘图。&lt;/li>
&lt;li>&lt;mark>问题&lt;/mark>：如果你有多个模型（比如一个三角形、一个正方形），每个模型都有自己的 &lt;code>VBO&lt;/code>、&lt;code>IBO&lt;/code> 和复杂的 &lt;code>VertexBufferLayout&lt;/code>（顶点布局）。&lt;/li>
&lt;li>&lt;mark>后果&lt;/mark>：每次切换模型画图，你都要重新写一遍 &lt;code>glBindBuffer&lt;/code>、&lt;code>glEnableVertexAttribArray&lt;/code> 和 &lt;code>glVertexAttribPointer&lt;/code>。这太啰嗦了！&lt;/li>
&lt;/ul>
&lt;h2 id="vao-的本质状态的存档">VAO 的本质：状态的“存档”&lt;a class="anchor" href="#vao-%e7%9a%84%e6%9c%ac%e8%b4%a8%e7%8a%b6%e6%80%81%e7%9a%84%e5%ad%98%e6%a1%a3">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>定义&lt;/mark>：VAO 就像是一个&lt;mark>配置记录仪&lt;/mark>。它不会存储实际的顶点坐标数据，但它会&lt;mark>记住&lt;/mark>：&lt;/p>
&lt;ol>
&lt;li>哪个 &lt;mark>VBO&lt;/mark> 与它绑定了。&lt;/li>
&lt;li>&lt;mark>属性布局&lt;/mark>（多少个 float、偏移量是多少、是否归一化）。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>优势&lt;/mark>：一旦你设置好了 VAO，下次画这个模型时，只需要一行 &lt;code>glBindVertexArray(vaoID)&lt;/code>，所有的 VBO 绑定和属性设置就会&lt;mark>瞬间还原&lt;/mark>。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h2 id="兼容性大坑core-vs-compatibility">兼容性大坑：Core vs Compatibility&lt;a class="anchor" href="#%e5%85%bc%e5%ae%b9%e6%80%a7%e5%a4%a7%e5%9d%91core-vs-compatibility">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>Compatibility Profile（兼容模式）&lt;/mark>：&lt;em>OpenGL 会默认帮你创建一个“隐藏的 VAO (ID为0)”。所以你之前不写 VAO 也能画出图&lt;/em>。&lt;/li>
&lt;li>&lt;mark>Core Profile（核心模式）&lt;/mark>：必须显式地 &lt;code>glGenVertexArrays&lt;/code>。如果不绑定 VAO 就直接调用 &lt;code>glVertexAttribPointer&lt;/code>，程序会直接崩溃或报错。&lt;/li>
&lt;li>&lt;mark>Cherno 的建议&lt;/mark>：永远手动创建 VAO，这样你的代码在任何显卡驱动和模式下都是健壮的。&lt;/li>
&lt;/ul>
&lt;h2 id="编码实践如何创建-vao">编码实践：如何创建 VAO&lt;a class="anchor" href="#%e7%bc%96%e7%a0%81%e5%ae%9e%e8%b7%b5%e5%a6%82%e4%bd%95%e5%88%9b%e5%bb%ba-vao">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>标准流程&lt;/mark>：&lt;/p>
&lt;ol>
&lt;li>&lt;code>unsigned int vao; glGenVertexArrays(1, &amp;amp;vao);&lt;/code>&lt;/li>
&lt;li>&lt;code>glBindVertexArray(vao);&lt;/code>&lt;/li>
&lt;li>&lt;code>glBindBuffer(GL_ARRAY_BUFFER, vbo);&lt;/code>&lt;/li>
&lt;li>&lt;code>glVertexAttribPointer(...);&lt;/code>&lt;/li>
&lt;li>&lt;code>glEnableVertexAttribArray(0);&lt;/code>&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>注意&lt;/mark>：顺序很重要！必须先绑定 VAO，再去绑定 VBO 和设置属性，这样 VAO 才能“录制”下这些操作。&lt;/p></description></item><item><title>11uniform</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/11uniform/</link><pubDate>Wed, 25 Mar 2026 07:52:27 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/11uniform/</guid><description>&lt;p>在之前的章节里，颜色是硬编码在着色器里的，而这一集教你如何从 CPU（C++ 代码）动态地控制 GPU 里的变量。&lt;/p>
&lt;h1 id="总结">总结&lt;a class="anchor" href="#%e6%80%bb%e7%bb%93">#&lt;/a>&lt;/h1>
&lt;h2 id="什么是-uniform">什么是 Uniform？&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af-uniform">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>定义&lt;/mark>：Uniform 是从 CPU 向 Shader 传递数据的桥梁。&lt;/li>
&lt;li>&lt;mark>特性&lt;/mark>：
&lt;ul>
&lt;li>&lt;mark>“统一”性&lt;/mark>：在一个 Draw Call（绘制指令）中，所有的顶点和像素看到的 Uniform 值都是完全一样的。&lt;/li>
&lt;li>&lt;mark>对比&lt;/mark>：与 &lt;code>attributes&lt;/code>（顶点属性）不同，属性是每个顶点都可能不同的（如坐标），而 Uniform 是全局一致的。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>用途&lt;/mark>：最常用于传递颜色、变换矩阵（旋转/平移/缩放）、纹理采样器等。&lt;/li>
&lt;/ul>
&lt;blockquote class='book-hint '>
&lt;p>uniform变量依赖 &lt;em>PCIe 总线&lt;/em> 进行 CPU 到 GPU 的数据拷贝。在 GPU 内部，Uniform 并不像顶点属性（Attribute）那样存在于一个巨大的流缓冲区中。它存储在 GPU 专门划拨的一块==常量寄存器（Constant Registers）或统一常量缓冲区（Uniform Storage）==中。在 Shader 运行期间，Uniform 是只读的 &lt;del>Uniform 的“只读”是指 单个 Draw Call 执行期间 它是静态的。在不同的 Draw Call 之间，你可以随意修改它。&lt;/del>&lt;/p>&lt;/blockquote>&lt;h2 id="在-shader-中声明-uniform">在 Shader 中声明 Uniform&lt;a class="anchor" href="#%e5%9c%a8-shader-%e4%b8%ad%e5%a3%b0%e6%98%8e-uniform">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>语法&lt;/mark>：在 GLSL 中使用 &lt;code>uniform&lt;/code> 关键字。&lt;/li>
&lt;li>&lt;mark>命名规范&lt;/mark>：Cherno 推荐使用 &lt;code>u_&lt;/code> 前缀（如 &lt;code>u_Color&lt;/code>），以便在代码中快速区分。&lt;/li>
&lt;li>&lt;mark>代码示例&lt;/mark>：&lt;/li>
&lt;/ul>
&lt;pre tabindex="0">&lt;code class="language-Fragment" data-lang="Fragment"> #shader fragment
 #version 330 core
 layout(location = 0) out vec4 color;
 uniform vec4 u_Color; // 声明 Uniform
 void main() {
 color = u_Color; // 使用该变量
 };&lt;/code>&lt;/pre>&lt;h2 id="获取-uniform-的位置-location">获取 Uniform 的位置 (Location)&lt;a class="anchor" href="#%e8%8e%b7%e5%8f%96-uniform-%e7%9a%84%e4%bd%8d%e7%bd%ae-location">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>核心函数&lt;/mark>：&lt;code>glGetUniformLocation(program, &amp;quot;u_Color&amp;quot;)&lt;/code>。&lt;/p></description></item><item><title>10错误处理</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/10%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/</link><pubDate>Tue, 24 Mar 2026 23:05:53 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/10%E9%94%99%E8%AF%AF%E5%A4%84%E7%90%86/</guid><description>&lt;p>如何&lt;mark>自动化地捕获 OpenGL 的报错&lt;/mark>。由于 OpenGL 是一个状态机且基于 C 语言 API，它不会像现代 C++ 那样抛出异常，所以需要特殊的调试技巧。&lt;/p>
&lt;h1 id="传统方案glgeterror">传统方案：&lt;code>glGetError&lt;/code>&lt;a class="anchor" href="#%e4%bc%a0%e7%bb%9f%e6%96%b9%e6%a1%88glgeterror">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>现状&lt;/mark>：OpenGL 的函数执行失败时，屏幕通常只是黑屏，没有任何提示。&lt;/li>
&lt;li>&lt;mark>原始手段&lt;/mark>：调用 &lt;code>glGetError()&lt;/code>。它会返回一个错误代码（如 1280 代表 &lt;code>GL_INVALID_ENUM&lt;/code>）。&lt;/li>
&lt;li>&lt;mark>痛点&lt;/mark>：这个函数只能一次返回&lt;mark>一个&lt;/mark>错误。如果产生了多个错误，你得在一个 &lt;code>while&lt;/code> 循环里不断调用它才能清空错误队列。&lt;/li>
&lt;/ul>
&lt;h1 id="进阶方案封装-glclearerror-与-gllogcall">进阶方案：封装 &lt;code>GLClearError&lt;/code> 与 &lt;code>GLLogCall&lt;/code>&lt;a class="anchor" href="#%e8%bf%9b%e9%98%b6%e6%96%b9%e6%a1%88%e5%b0%81%e8%a3%85-glclearerror-%e4%b8%8e-gllogcall">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>思路&lt;/mark>：为了不让主代码被 &lt;code>glGetError&lt;/code> 淹没，Cherno 进行了宏封装。&lt;/li>
&lt;li>&lt;mark>&lt;code>GLCheckError()&lt;/code>&lt;/mark>：在执行 OpenGL 指令&lt;mark>前&lt;/mark>调用，用来清空之前的旧错误。&lt;/li>
&lt;li>&lt;mark>&lt;code>GLLogCall()&lt;/code>&lt;/mark>：在指令执行&lt;mark>后&lt;/mark>调用，检查是否有新错误产生，并打印出&lt;mark>文件名&lt;/mark>、&lt;mark>行号&lt;/mark>和&lt;mark>具体函数名&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;h1 id="神奇的宏assert-与--运算符">神奇的宏：&lt;code>ASSERT&lt;/code> 与 &lt;code>#&lt;/code> 运算符&lt;a class="anchor" href="#%e7%a5%9e%e5%a5%87%e7%9a%84%e5%ae%8fassert-%e4%b8%8e--%e8%bf%90%e7%ae%97%e7%ac%a6">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>自动化&lt;/mark>：定义一个 &lt;code>GLCall(x)&lt;/code> 宏。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-scss" data-lang="scss">&lt;span style="display:flex;">&lt;span>#define &lt;span style="color:#f92672">GLCall&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#f92672">x&lt;/span>&lt;span style="color:#f92672">)&lt;/span> &lt;span style="color:#f92672">GLClearError&lt;/span>&lt;span style="color:#f92672">()&lt;/span>;&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">x&lt;/span>;&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#f92672">ASSERT&lt;/span>&lt;span style="color:#f92672">(&lt;/span>&lt;span style="color:#f92672">GLLogCall&lt;/span>&lt;span style="color:#f92672">(&lt;/span>#x&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">__FILE__&lt;/span>&lt;span style="color:#f92672">,&lt;/span> &lt;span style="color:#f92672">__LINE__&lt;/span>&lt;span style="color:#f92672">))&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;mark>技巧&lt;/mark>：&lt;/p>
&lt;ul>
&lt;li>&lt;code>#x&lt;/code>：将代码内容转为字符串。&lt;/li>
&lt;li>&lt;code>__FILE__&lt;/code> 和 &lt;code>__LINE__&lt;/code>：C++ 内置宏，自动获取报错位置。&lt;/li>
&lt;li>&lt;code>ASSERT&lt;/code>：如果报错，直接让程序停在出问题的那一行，而不是跑飞。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="现代方案gldebugmessagecallback">现代方案：&lt;code>glDebugMessageCallback&lt;/code>&lt;a class="anchor" href="#%e7%8e%b0%e4%bb%a3%e6%96%b9%e6%a1%88gldebugmessagecallback">#&lt;/a>&lt;/h1>
&lt;p>&lt;del>视频没讲到这个&lt;/del>&lt;/p>
&lt;ul>
&lt;li>&lt;mark>新特性&lt;/mark>：在 OpenGL 4.3+ 版本中引入。&lt;/li>
&lt;li>&lt;mark>优势&lt;/mark>：这是“被动式”报错。你只需在初始化时设置一个回调函数，一旦 OpenGL 出错，驱动程序会自动跳进你的函数。&lt;/li>
&lt;li>&lt;mark>局限性&lt;/mark>：虽然更现代，但某些旧显卡驱动支持不佳。Cherno 推荐在学习阶段使用 &lt;code>GLCall&lt;/code> 宏，因为它兼容性最强且更直观。&lt;/li>
&lt;/ul>
&lt;h1 id="实战演示故意写错代码">实战演示：故意写错代码&lt;a class="anchor" href="#%e5%ae%9e%e6%88%98%e6%bc%94%e7%a4%ba%e6%95%85%e6%84%8f%e5%86%99%e9%94%99%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>验证&lt;/mark>：Cherno 故意在 &lt;code>glDrawElements&lt;/code> 里传了一个错误的枚举值。&lt;/li>
&lt;li>&lt;mark>结果&lt;/mark>：控制台瞬间精准报出了：
&lt;ol>
&lt;li>哪个函数错了（&lt;code>glDrawElements&lt;/code>）。&lt;/li>
&lt;li>在哪个文件哪一行。&lt;/li>
&lt;li>错误代码是什么。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h1 id="-博客总结金句重点">💡 博客总结（金句/重点）&lt;a class="anchor" href="#-%e5%8d%9a%e5%ae%a2%e6%80%bb%e7%bb%93%e9%87%91%e5%8f%a5%e9%87%8d%e7%82%b9">#&lt;/a>&lt;/h1>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>知识点&lt;/th>
 &lt;th>关键点&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;mark>为什么 OpenGL 不报错？&lt;/mark>&lt;/td>
 &lt;td>它是 C 风格 API，不提供异常机制，需手动查询状态。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;mark>&lt;code>glGetError&lt;/code> 特点&lt;/mark>&lt;/td>
 &lt;td>错误码是累积的，必须循环读取直到返回 &lt;code>GL_NO_ERROR&lt;/code>。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;mark>&lt;code>GLCall&lt;/code> 宏的作用&lt;/mark>&lt;/td>
 &lt;td>它可以包裹任何 &lt;code>gl&lt;/code> 函数，实现一站式“清空-执行-检查”。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;mark>调试效率&lt;/mark>&lt;/td>
 &lt;td>配合 &lt;code>__debugbreak()&lt;/code>（Windows 特有）可以让调试器直接定位到崩掉的那行源码。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>&lt;mark>在发布版本（Release）中通常要关掉这些报错检查&lt;/mark>。因为频繁地通过总线询问 GPU 状态会严重拖慢帧率（FPS）。&lt;/p></description></item><item><title>09顶点缓冲区</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/09%E9%A1%B6%E7%82%B9%E7%BC%93%E5%86%B2%E5%8C%BA/</link><pubDate>Tue, 24 Mar 2026 19:10:23 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/09%E9%A1%B6%E7%82%B9%E7%BC%93%E5%86%B2%E5%8C%BA/</guid><description>&lt;h1 id="总述">总述&lt;a class="anchor" href="#%e6%80%bb%e8%bf%b0">#&lt;/a>&lt;/h1>
&lt;h2 id="核心痛点重复的顶点数据">核心痛点：重复的顶点数据&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e7%97%9b%e7%82%b9%e9%87%8d%e5%a4%8d%e7%9a%84%e9%a1%b6%e7%82%b9%e6%95%b0%e6%8d%ae">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>现状分析&lt;/mark>：绘制一个矩形需要两个三角形（6 个顶点）。&lt;/li>
&lt;li>&lt;mark>资源浪费&lt;/mark>：矩形只有 4 个角，使用 &lt;code>glDrawArrays&lt;/code> 必须重复定义其中 2 个顶点（坐标、纹理、颜色等完全一致）。&lt;/li>
&lt;li>&lt;mark>影响&lt;/mark>：随着模型复杂化，这种冗余会成倍消耗显存（VRAM）和带宽。&lt;/li>
&lt;/ul>
&lt;h2 id="解决方案index-buffer-原理">解决方案：Index Buffer 原理&lt;a class="anchor" href="#%e8%a7%a3%e5%86%b3%e6%96%b9%e6%a1%88index-buffer-%e5%8e%9f%e7%90%86">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>&lt;mark>定义&lt;/mark>：索引缓冲区（IBO/EBO）存储的是指向顶点数组的&lt;mark>整数索引&lt;/mark>。&lt;/li>
&lt;li>&lt;mark>逻辑&lt;/mark>：
&lt;ol>
&lt;li>&lt;mark>Vertex Buffer&lt;/mark>：只存储 4 个唯一的顶点坐标。&lt;/li>
&lt;li>&lt;mark>Index Buffer&lt;/mark>：存储顺序（如 &lt;code>0, 1, 2, 2, 3, 0&lt;/code>），告诉 GPU 如何连接这些点。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;mark>优势&lt;/mark>：一个浮点数顶点属性通常 12-32 字节，而一个索引（&lt;code>unsigned int&lt;/code> 或 &lt;code>short&lt;/code>）仅需 4 或 2 字节。&lt;/li>
&lt;/ul>
&lt;h2 id="编码实践创建与绑定-ibo">编码实践：创建与绑定 IBO&lt;a class="anchor" href="#%e7%bc%96%e7%a0%81%e5%ae%9e%e8%b7%b5%e5%88%9b%e5%bb%ba%e4%b8%8e%e7%bb%91%e5%ae%9a-ibo">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>创建对象&lt;/mark>：&lt;code>glGenBuffers(1, &amp;amp;ibo);&lt;/code>&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>绑定目标&lt;/mark>：必须指定为 &lt;mark>&lt;code>GL_ELEMENT_ARRAY_BUFFER&lt;/code>&lt;/mark>。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>填充数据&lt;/mark>：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> indices[] &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>, &lt;span style="color:#ae81ff">0&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//索引缓冲区：index buffer object
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> ibo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 生成一个缓冲区 ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>glGenBuffers(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>ibo);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 绑定该 ID 到元素数组缓冲区 (Element Array Buffer)插槽，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//也称索引缓冲区对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 将顶点数据从 CPU 内存拷贝到 GPU 显存，设为静态读取模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>glBufferData(GL_ELEMENT_ARRAY_BUFFER, &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	indices, GL_STATIC_DRAW);&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;/li>
&lt;li>
&lt;p>&lt;mark>注意&lt;/mark>：索引必须是正整数，且建议使用 &lt;code>unsigned int&lt;/code> 以保证最大兼容性。&lt;/p></description></item><item><title>08处理着色器</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/08%E5%A4%84%E7%90%86%E7%9D%80%E8%89%B2%E5%99%A8/</link><pubDate>Tue, 24 Mar 2026 16:37:11 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/08%E5%A4%84%E7%90%86%E7%9D%80%E8%89%B2%E5%99%A8/</guid><description>&lt;p>主要是添加了&lt;code>struct ShaderProgramSource&lt;/code> 和&lt;code>static ShaderProgramSource ParseShader(const std::string&amp;amp; filepath)&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP08
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;GL/glew.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;GLFW/glfw3.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;fstream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;sstream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">ShaderProgramSource&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string VertexSource;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string FragmentSource;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> ShaderProgramSource &lt;span style="color:#a6e22e">ParseShader&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filepath)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ShaderType&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		NONE &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>,VERTEX &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>,FRAGMENT &lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//input file stream
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>ifstream stream(filepath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string line;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>stringstream ss[&lt;span style="color:#ae81ff">2&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ShaderType type &lt;span style="color:#f92672">=&lt;/span> ShaderType&lt;span style="color:#f92672">::&lt;/span>NONE;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">while&lt;/span> (getline(stream, line))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (line.find(&lt;span style="color:#e6db74">&amp;#34;#shader&amp;#34;&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">::&lt;/span>npos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">if&lt;/span> (line.find(&lt;span style="color:#e6db74">&amp;#34;vertex&amp;#34;&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">::&lt;/span>npos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				type &lt;span style="color:#f92672">=&lt;/span> ShaderType&lt;span style="color:#f92672">::&lt;/span>VERTEX;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (line.find(&lt;span style="color:#e6db74">&amp;#34;fragment&amp;#34;&lt;/span>) &lt;span style="color:#f92672">!=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">::&lt;/span>npos)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>				type &lt;span style="color:#f92672">=&lt;/span> ShaderType&lt;span style="color:#f92672">::&lt;/span>FRAGMENT;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			ss[(&lt;span style="color:#66d9ef">int&lt;/span>)type] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> line &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#39;\n&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> { ss[&lt;span style="color:#ae81ff">0&lt;/span>].str(),ss[&lt;span style="color:#ae81ff">1&lt;/span>].str() };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//GLenum也就是unsigned int,这里不用GLenum是为了解耦
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">CompileShader&lt;/span>(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> type,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> source)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建着色器对象，向 OpenGL 申请一个空的“容器”来存放你的代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//把光标放在 glCreateShader( 的左括号后面，然后按下 Ctrl + Shift + Space。会弹出一个小黑框，显示：GLuint glCreateShader(GLenum type)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//到glew.h搜索，发现typedef unsigned int GLenum;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> id &lt;span style="color:#f92672">=&lt;/span> glCreateShader(type);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//返回一个指向该字符串首地址的只读指针（const char*）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> src &lt;span style="color:#f92672">=&lt;/span> source.c_str();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//有了容器后，你需要把写好的字符串代码塞进去（拷贝）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3种用法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//1. glShaderSource(id, 1, &amp;amp;src, nullptr);	只有一个字符串，且它是以 \0 结尾的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. glShaderSource(id, 1, &amp;amp;src, &amp;amp;len);	只有一个字符串，长度由 len 指定。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3. glShaderSource(id, 2, strings, lengths);	有两个字符串片段（数组形式），长度分别由 lengths[0] 和 lengths[1] 指定。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glShaderSource(id, &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>src, &lt;span style="color:#66d9ef">nullptr&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//将你的 GLSL 代码翻译成显卡能理解的机器指令
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glCompileShader(id);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//错误处理
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 查询编译状态：询问 OpenGL 这个 shader 编译成功了吗？
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// GL_COMPILE_STATUS 会把结果存入 result 中（成功为 GL_TRUE，失败为 GL_FALSE）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glGetShaderiv(id, GL_COMPILE_STATUS, &lt;span style="color:#f92672">&amp;amp;&lt;/span>result);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (result &lt;span style="color:#f92672">==&lt;/span> GL_FALSE)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">int&lt;/span> length;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//获取错误日志长度：如果编译失败，先问一下错误信息一共有多少个字符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glGetShaderiv(id, GL_INFO_LOG_LENGTH, &lt;span style="color:#f92672">&amp;amp;&lt;/span>length);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在栈上申请内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//如果申请的内存太大，alloca会导致栈溢出（1MB）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)alloca(length &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">char&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//提取错误信息：把显卡驱动里的具体报错文字拷贝到我们刚才申请的 message 内存中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glGetShaderInfoLog(id, length, &lt;span style="color:#f92672">&amp;amp;&lt;/span>length, message);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Failed to compile &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> ((type &lt;span style="color:#f92672">==&lt;/span> GL_VERTEX_SHADER) &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#e6db74">&amp;#34;vertex&amp;#34;&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;fragment&amp;#34;&lt;/span>) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; shader!&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//清理：编译失败了，这个 shader 对象也就没用了，删掉它防止内存泄漏
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glDeleteShader(id);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> id;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">CreateShader&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertexShader,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> fragmentShader)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在 GPU 中申请一个空的“程序对象”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> program &lt;span style="color:#f92672">=&lt;/span> glCreateProgram();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译顶点着色器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> vs &lt;span style="color:#f92672">=&lt;/span> CompileShader(GL_VERTEX_SHADER,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		vertexShader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译片段着色器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> fs &lt;span style="color:#f92672">=&lt;/span> CompileShader(GL_FRAGMENT_SHADER,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		fragmentShader);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//把已经编译好的顶点着色器和片段着色器附加到程序对象中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glAttachShader(program, vs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glAttachShader(program, fs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//链接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glLinkProgram(program);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//验证当前的程序是否能在当前的 OpenGL 状态下执行（
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 检查顶点着色器的输出是否与片段着色器的输入匹配，并
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 生成最终的可执行二进制代码。）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glValidateProgram(program);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//删除临时的中间产物（类似编译完 C++ 后删除 .obj
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glDeleteShader(vs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	glDeleteShader(fs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> program;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>(&lt;span style="color:#66d9ef">void&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#pragma region 一些初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	GLFWwindow&lt;span style="color:#f92672">*&lt;/span> window;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 初始化 GLFW 库，失败则退出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>glfwInit())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//强制指定使用 Core Profile（核心模式），如果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//没有手动写着色器则不会渲染；如果不是核心模式，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//在固定管线中默认颜色是白色，且默认顶点在NDC标准
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//设备坐标系中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 创建窗口对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	window &lt;span style="color:#f92672">=&lt;/span> glfwCreateWindow(&lt;span style="color:#ae81ff">640&lt;/span>, &lt;span style="color:#ae81ff">480&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>, NULL, NULL);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>window)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 创建失败则清理并退出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwTerminate();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 将当前窗口的上下文设置为 OpenGL 渲染的目标
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glfwMakeContextCurrent(window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 初始化 GLEW 以加载 OpenGL 函数指针，需在有上下文后执行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (glewInit() &lt;span style="color:#f92672">!=&lt;/span> GLEW_OK)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Error!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#pragma endregion
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 定义三角形的顶点坐标（CPU 内存）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">float&lt;/span> positions[&lt;span style="color:#ae81ff">6&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#ae81ff">0.0f&lt;/span>, &lt;span style="color:#ae81ff">0.5f&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 生成一个缓冲区 ID
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glGenBuffers(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">&amp;amp;&lt;/span>buffer);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 绑定该 ID 到顶点缓冲区插槽
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glBindBuffer(GL_ARRAY_BUFFER, buffer);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 将顶点数据从 CPU 内存拷贝到 GPU 显存，设为静态读取模式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glBufferData(GL_ARRAY_BUFFER, &lt;span style="color:#ae81ff">6&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>),
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		positions, GL_STATIC_DRAW);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 启用索引为 0 的(顶点)属性 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glEnableVertexAttribArray(&lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//1. 打标签：它把当前 GL_ARRAY_BUFFER 里的数据流，贴上了“0号”的标签。2. 定规则：它告诉 GPU，当你（Shader）想要 location = 0 的数据时，请按照“每 2 个 float 为一组”的规则去缓存里抓取。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glVertexAttribPointer(&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, GL_FLOAT, GL_FALSE, &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>) &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>, (&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个相对路径，相对于 工作目录
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果不是在visual studio中运行，就会相对于 可执行文件 所在的目录
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果在visual studio中，工作目录被设置为$(ProjectDir) (右键目录-属性-调试-woking directory)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ShaderProgramSource source &lt;span style="color:#f92672">=&lt;/span> ParseShader(&lt;span style="color:#e6db74">&amp;#34;res/shaders/Basic.shader&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> source.VertexSource &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> source.FragmentSource &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 将字符串源码编译并链接成一个完整的程序对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> program &lt;span style="color:#f92672">=&lt;/span> CreateShader(source.VertexSource, source.FragmentSource);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 告诉 OpenGL 状态机：接下来的所有绘制指令（如 glDrawArrays）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 都请使用这个编译好的着色器程序进行渲染
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glUseProgram(program);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 游戏/渲染主循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">while&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>glfwWindowShouldClose(window))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 清理屏幕颜色缓冲区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glClear(GL_COLOR_BUFFER_BIT);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 读取当前绑定的缓冲区数据并绘制三角形：从
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 索引0即第1个顶点开始画，读取三个顶点(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//并行地读第1个顶点的0号属性_以及_第1个顶点的1号属性) 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glDrawArrays(GL_TRIANGLES, &lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 交换前后缓冲区以刷新画面
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwSwapBuffers(window);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 轮询并处理窗口事件（如键盘输入、关闭动作）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		glfwPollEvents();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 手动通知显卡驱动释放该程序占用的显存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glDeleteProgram(program);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 退出前清理资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	glfwTerminate();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>着色器&lt;/p></description></item><item><title>07编写一个着色器</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/07%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AA%E7%9D%80%E8%89%B2%E5%99%A8/</link><pubDate>Tue, 24 Mar 2026 12:31:46 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/07%E7%BC%96%E5%86%99%E4%B8%80%E4%B8%AA%E7%9D%80%E8%89%B2%E5%99%A8/</guid><description>&lt;h1 id="概述">概述&lt;a class="anchor" href="#%e6%a6%82%e8%bf%b0">#&lt;/a>&lt;/h1>
&lt;p>编写最基础的&lt;mark>顶点着色器 (Vertex Shader)&lt;/mark> 和&lt;mark>片段着色器 (Fragment Shader)&lt;/mark>，并将它们链接成一个可以在显卡上运行的着色器程序。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>课程引入&lt;/mark> 回顾上一集关于着色器的理论概念，明确本集目标：编写实际代码让上一集绘制的三角形呈现特定的颜色（不再是默认的白色或黑色）。&lt;/li>
&lt;li>&lt;mark>创建基础字符串结构&lt;/mark> 演示如何在 C++ 中以字符串形式编写 GLSL 代码。由于目前还没有文件读取系统，Cherno 直接在 &lt;code>main&lt;/code> 函数中使用原始字符串（Raw Strings）来定义顶点和片段着色器的源码。&lt;/li>
&lt;li>&lt;mark>编写顶点着色器 (Vertex Shader)&lt;/mark>
&lt;ul>
&lt;li>指定版本：&lt;code>#version 330 core&lt;/code>。&lt;/li>
&lt;li>定义输入属性：&lt;code>layout(location = 0) in vec4 position;&lt;/code>&lt;/li>
&lt;li>主函数 &lt;code>main&lt;/code>：将输入的坐标赋值给内置变量 &lt;code>gl_Position&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>编写片段着色器 (Fragment Shader)&lt;/mark>
&lt;ul>
&lt;li>定义输出颜色：&lt;code>layout(location = 0) out vec4 color;&lt;/code>&lt;/li>
&lt;li>主函数 &lt;code>main&lt;/code>：为像素指定颜色值（例如红色 &lt;code>vec4(1.0, 0.0, 0.0, 1.0)&lt;/code>）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>创建编译与链接函数 &lt;code>CreateShader&lt;/code>&lt;/mark> 开始实现逻辑：如何将上述两个字符串交给 OpenGL。
&lt;ul>
&lt;li>调用 &lt;code>glCreateProgram&lt;/code> 创建一个程序容器。&lt;/li>
&lt;li>调用自定义的 &lt;code>CompileShader&lt;/code> 函数分别编译顶点和片段部分。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>实现 &lt;code>CompileShader&lt;/code> 函数&lt;/mark> 这是核心步骤：
&lt;ol>
&lt;li>&lt;code>glCreateShader&lt;/code>：根据类型创建着色器对象。&lt;/li>
&lt;li>&lt;code>glShaderSource&lt;/code>：将 C++ 字符串传递给 OpenGL。&lt;/li>
&lt;li>&lt;code>glCompileShader&lt;/code>：调用显卡驱动进行编译。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;mark>错误处理与调试 (Shader Debugging)&lt;/mark> 这是新手最容易卡住的地方。Cherno 详细演示了如何使用 &lt;code>glGetShaderiv&lt;/code> 检查编译状态，并用 &lt;code>glGetShaderInfoLog&lt;/code> 打印出显卡报错信息。&lt;/li>
&lt;li>&lt;mark>链接着色器程序 (Linking)&lt;/mark> 使用 &lt;code>glAttachShader&lt;/code> 将编译好的两个着色器附加到程序上，然后调用 &lt;code>glLinkProgram&lt;/code> 进行链接，最后用 &lt;code>glValidateProgram&lt;/code> 验证。&lt;/li>
&lt;li>&lt;mark>清理工作&lt;/mark> 链接成功后，调用 &lt;code>glDeleteShader&lt;/code> 删除临时的中间产物（类似编译完 C++ 后删除 &lt;code>.obj&lt;/code> 文件），以节省资源。&lt;/li>
&lt;li>&lt;mark>实际运行测试&lt;/mark> 将编写好的 &lt;code>CreateShader&lt;/code> 函数集成到渲染循环之前。&lt;/li>
&lt;li>&lt;mark>结果展示与总结&lt;/mark> 屏幕上成功出现了一个红色的三角形。Cherno 总结了着色器在现代渲染管线中的重要角色。&lt;/li>
&lt;/ul>
&lt;p>&lt;mark>学习要点提示：&lt;/mark>&lt;/p></description></item><item><title>06着色器原理</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/06%E7%9D%80%E8%89%B2%E5%99%A8%E5%8E%9F%E7%90%86/</link><pubDate>Mon, 23 Mar 2026 16:29:24 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/06%E7%9D%80%E8%89%B2%E5%99%A8%E5%8E%9F%E7%90%86/</guid><description>&lt;h1 id="什么是着色器-shaders">什么是着色器 (Shaders)&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e7%9d%80%e8%89%b2%e5%99%a8-shaders">#&lt;/a>&lt;/h1>
&lt;p>着色器本质上是&lt;em>运行在 GPU（显卡）上的程序&lt;/em>。在 OpenGL 绘图流程中，我们需要&lt;em>在 GPU 上运行代码来处理我们发送过去的顶点数据&lt;/em>。&lt;/p>
&lt;ul>
&lt;li>当你调用 glCompileShader(id) 时，显卡驱动（运行在 CPU 上）会获取这个字符串。&lt;em>&lt;mark>显卡驱动&lt;/mark>里内置了一个编译器&lt;/em>。它会&lt;em>将你的 GLSL 源代码翻译成该显卡硬件能听懂的机器码（微指令）&lt;/em>。由于不同品牌的显卡（NVIDIA, AMD, Intel）底层指令集完全不同，所以 Shader 必须在你的电脑上“现场编译”，而不能像 C++ 那样预先编译成 .exe。&lt;em>编译好的二进制指令会被发送并存储在 GPU 的显存中&lt;/em>。当你执行 glDrawArrays 时，GPU 会激活这些指令，大规模并行地处理你传进去的顶点数据。&lt;/li>
&lt;li>我们需要显卡的能力在屏幕上绘制图形，所以需要程序完全在显卡上运行，当然部分代码需要在CPU上运行&lt;/li>
&lt;li>着色器的本质，就是告诉GPU如何处理CPU发送给他的数据&lt;/li>
&lt;/ul>
&lt;h1 id="渲染管线概述-the-graphics-pipeline">渲染管线概述 (The Graphics Pipeline)&lt;a class="anchor" href="#%e6%b8%b2%e6%9f%93%e7%ae%a1%e7%ba%bf%e6%a6%82%e8%bf%b0-the-graphics-pipeline">#&lt;/a>&lt;/h1>
&lt;p>解释了&lt;em>数据从 CPU 发送到 GPU 后的处理过程&lt;/em>。&lt;em>渲染管线&lt;/em>是一系列&lt;em>将 3D 坐标转换为屏幕上 2D 像素&lt;/em>的步骤。&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>渲染&lt;em>管道&lt;/em>：在CPU上写了一堆数据，之后向显卡发送了一些数据，然后发送了DrawCall指令（发送指令前绑定了一些状态），最后进入了着色器的阶段，GPU实际处理DrawCall指令并在屏幕上绘制一些东西&lt;/p>&lt;/blockquote>&lt;h1 id="着色器">着色器&lt;a class="anchor" href="#%e7%9d%80%e8%89%b2%e5%99%a8">#&lt;/a>&lt;/h1>
&lt;p>顶点着色器和片段着色器是顺着管道的两种不同的着色器类型，发出DrawCall指令后，顶点着色器被执行，然后再经过一些阶段后 是片段着色器&lt;/p>
&lt;p>&lt;em>&lt;mark>顶点着色器&lt;/mark>&lt;/em> &lt;del>把 3D 空间的坐标转换成屏幕上的 2D 坐标（术语叫标准化设备坐标）&lt;/del> -&amp;gt;&lt;em>几何着色器&lt;/em> &lt;del>增减图形：可以把一个点变成一个三角形，或者把一个三角形删掉。这里，几何着色器根据这 3 个点，计算出了第 4 个点的位置，并把它们重新组合。输出：它“发射”出了足够的顶点，组成了两个独立的三角形图元。&lt;/del> -&amp;gt;图元组装 &lt;del>把处理好的点“连线”&lt;/del> -&amp;gt;光栅化 &lt;del>计算这个三角形到底盖住了屏幕上哪些像素格子&lt;/del> -&amp;gt;&lt;em>&lt;mark>片段着色器&lt;/mark>&lt;/em> &lt;del>根据光照、纹理、材质，给这个像素算出一个最终的 RGBA 值&lt;/del> -&amp;gt;测试与混合 &lt;del>深度测试 (Depth Test)：检查这个像素是不是被别的物体挡住了。模板测试：一些特殊遮罩效果。混合 (Blending)：如果是半透明的，就把它和背景颜色融合&lt;/del>&lt;/p></description></item><item><title>05顶点属性和内存布局</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/05%E9%A1%B6%E7%82%B9%E5%B1%9E%E6%80%A7%E5%92%8C%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80/</link><pubDate>Sun, 22 Mar 2026 18:53:01 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/05%E9%A1%B6%E7%82%B9%E5%B1%9E%E6%80%A7%E5%92%8C%E5%86%85%E5%AD%98%E5%B8%83%E5%B1%80/</guid><description>&lt;p>在第 04 集里你把数据塞进了显存，但 GPU 面对那一串二进制数字是“瞎”的。这一集的核心就是&lt;mark>给数据贴标签&lt;/mark>，告诉 GPU 如何读取这些坐标。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>问题的引入：为什么屏幕还是黑的？&lt;/mark>
&lt;ul>
&lt;li>数据（Positions）已经在 VRAM 里了，但 GPU 不知道这堆 &lt;code>float&lt;/code> 代表什么。&lt;/li>
&lt;li>是一组 坐标？还是 颜色？或者是贴图坐标？&lt;/li>
&lt;li>我们需要一份“说明书”来定义数据的&lt;mark>布局 (Layout)&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>核心函数：&lt;code>glVertexAttribPointer&lt;/code> 详解&lt;/mark>
&lt;ul>
&lt;li>这是 OpenGL 中参数最复杂的函数，Cherno 逐一拆解了这 6 个参数：
&lt;ol>
&lt;li>&lt;mark>index&lt;/mark>: 属性的索引（例如：0号属性给位置，1号属性给颜色，2号属性给纹理）。&lt;/li>
&lt;li>&lt;mark>size&lt;/mark>: 每个属性包含几个分量（位置是3，纹理是2）。&lt;/li>
&lt;li>&lt;mark>type&lt;/mark>: 数据类型（&lt;code>GL_FLOAT&lt;/code>）。&lt;/li>
&lt;li>&lt;mark>normalized&lt;/mark>: 是否归一化（通常选 &lt;code>GL_FALSE&lt;/code>）。&lt;/li>
&lt;li>&lt;mark>stride (步长)&lt;/mark>: &lt;mark>最关键参数&lt;/mark>。从&lt;em>某个属性的起始点&lt;/em>到&lt;em>下一个属性起始点&lt;/em>的字节数。（这里第一组到第二组，位置index从0-&amp;gt;5，纹理index从3-&amp;gt;8，这里是&lt;code>5 * sizeof(float)&lt;/code>）&lt;/li>
&lt;li>&lt;mark>pointer (偏移量)&lt;/mark>: 在单个顶点数据块内，该属性距离(这个块的)起始位置的字节偏移。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//这里举一个特殊的例子，LearnOpenGL中的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">float&lt;/span> vertices[] &lt;span style="color:#f92672">=&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">0.0f&lt;/span>, &lt;span style="color:#ae81ff">0.0f&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>, &lt;span style="color:#ae81ff">0.0f&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>, &lt;span style="color:#ae81ff">1.0f&lt;/span>,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//配置位置属性
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>glVertexAttribPointer(&lt;span style="color:#ae81ff">0&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>, GL_FLOAT, GL_FALSE, &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>), (&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#ae81ff">0&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>glEnableVertexAttribArray(&lt;span style="color:#ae81ff">0&lt;/span>); 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//配置纹理属性
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>glVertexAttribPointer(&lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, GL_FLOAT, GL_FALSE, &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>), (&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)(&lt;span style="color:#ae81ff">3&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>)));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//第二个2，和上面第一个参数，也就是 vs文件中的location一致，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//表示要启用 2 号属性（对应纹理）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>glEnableVertexAttribArray(&lt;span style="color:#ae81ff">2&lt;/span>);&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;mark>内存布局的可视化演示&lt;/mark>
&lt;ul>
&lt;li>Cherno 使用画图工具展示了数据在内存中是如何排列的。&lt;/li>
&lt;li>如果每个顶点只有 2 个 &lt;code>float&lt;/code> 坐标，那么 &lt;mark>Stride&lt;/mark> 就是 &lt;code>2 * sizeof(float)&lt;/code>。&lt;/li>
&lt;li>如果以后加上纹理坐标（又多 2 个 &lt;code>float&lt;/code>），&lt;mark>Stride&lt;/mark> 就会变成 &lt;code>4 * sizeof(float)&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>启用顶点属性 (&lt;code>glEnableVertexAttribArray&lt;/code>)&lt;/mark>
&lt;ul>
&lt;li>仅仅定义了“说明书”还不够，必须通过这个函数&lt;mark>手动开启对应的属性索引&lt;/mark>（本例中是 0）。&lt;/li>
&lt;li>默认情况下，为了性能，所有属性槽位都是关闭的。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>链接缓冲区与属性&lt;/mark>
&lt;ul>
&lt;li>强调了一个隐式逻辑：&lt;code>glVertexAttribPointer&lt;/code> 关联的是&lt;mark>当前绑定在 &lt;code>GL_ARRAY_BUFFER&lt;/code> 上的那个 ID&lt;/mark>。&lt;/li>
&lt;li>这再次体现了 OpenGL “状态机”的特性。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>总结与运行结果&lt;/mark>
&lt;ul>
&lt;li>加上这两行关键代码后，配合默认或简单的着色器，屏幕上终于能画出三角形的轮廓了。&lt;/li>
&lt;li>预告：下一集将进入 &lt;mark>Shader (着色器)&lt;/mark> 的世界，那是真正赋予图形灵魂的地方。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>核心操作流程（接续你的代码）&lt;/li>
&lt;/ul>
&lt;p>在你的 &lt;code>glBufferData&lt;/code> 之后，必须补充这两行，否则 &lt;code>glDrawArrays&lt;/code> 找不到数据：&lt;/p></description></item><item><title>04顶点缓冲区和绘制三角形</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/04%E9%A1%B6%E7%82%B9%E7%BC%93%E5%86%B2%E5%8C%BA%E5%92%8C%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2/</link><pubDate>Sun, 22 Mar 2026 16:24:13 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/04%E9%A1%B6%E7%82%B9%E7%BC%93%E5%86%B2%E5%8C%BA%E5%92%8C%E7%BB%98%E5%88%B6%E4%B8%89%E8%A7%92%E5%BD%A2/</guid><description>&lt;h1 id="总述">总述&lt;a class="anchor" href="#%e6%80%bb%e8%bf%b0">#&lt;/a>&lt;/h1>
&lt;p>这一集（时长 20:06）标志着你正式从“配置环境”跨越到了“图形编程”。这里讲解了现代 OpenGL 的灵魂：&lt;mark>如何把 CPU 内存里的数据塞进 GPU 显存里&lt;/mark>。&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>什么是顶点缓冲区 (Vertex Buffer / VBO)？&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>&lt;mark>核心定义&lt;/mark>：它本质上是 GPU 显存中的一块内存区域，用于存储顶点的各种数据（坐标、颜色等）。&lt;/li>
&lt;li>&lt;mark>为什么要用它？&lt;/mark>：CPU 到 GPU 的总线传输相对较慢。我们希望一次性把大量数据推送到显存，然后让 GPU 在内部高速读取，而不是每帧都由 CPU “手把手”教 GPU 怎么画。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>定义顶点数据&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>在 C++ 中创建一个浮点数数组 &lt;code>float positions[6]&lt;/code>，存入三个顶点的 坐标。&lt;/li>
&lt;li>注意：此时这些数据还在 &lt;mark>RAM（内存）&lt;/mark> 中，GPU 还看不见它们。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>生成缓冲区 ID (&lt;code>glGenBuffers&lt;/code>)&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>OpenGL 是基于状态机的。我们不直接操作对象指针，而是操作 &lt;mark>ID (unsigned int)&lt;/mark>。&lt;/li>
&lt;li>调用 &lt;code>glGenBuffers(1, &amp;amp;buffer)&lt;/code>：向 OpenGL 申请一个 ID，代表我们要创建的一个缓冲区。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>绑定缓冲区 (&lt;code>glBindBuffer&lt;/code>)&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>这是初学者最容易晕的地方。OpenGL 像是一个只有一个插槽的播放器。&lt;/li>
&lt;li>调用 &lt;code>glBindBuffer(GL_ARRAY_BUFFER, buffer)&lt;/code>：告诉 OpenGL，“从现在起，所有关于 &lt;code>GL_ARRAY_BUFFER&lt;/code> 的操作，都请针对我刚刚申请的这个 &lt;code>buffer&lt;/code> 进行”。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>填充数据 (&lt;code>glBufferData&lt;/code>)&lt;/mark>&lt;/p>
&lt;ul>
&lt;li>这是真正发生“搬运”动作的代码。&lt;/li>
&lt;li>参数解释：
&lt;ol>
&lt;li>目标：&lt;code>GL_ARRAY_BUFFER&lt;/code>。&lt;/li>
&lt;li>大小：&lt;code>6 * sizeof(float)&lt;/code>。&lt;/li>
&lt;li>数据指针：&lt;code>positions&lt;/code>。&lt;/li>
&lt;li>使用方式：&lt;code>GL_STATIC_DRAW&lt;/code>（告诉显卡：这些数据我画一次后基本不动了，请优化存储）。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>为什么屏幕上还是没东西？&lt;/mark>&lt;/p></description></item><item><title>01-03基础配置</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/01-03%E5%9F%BA%E7%A1%80%E9%85%8D%E7%BD%AE/</link><pubDate>Sat, 21 Mar 2026 19:43:45 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/cherno_opengl/01-03%E5%9F%BA%E7%A1%80%E9%85%8D%E7%BD%AE/</guid><description>&lt;h1 id="01-03基础配置">01-03基础配置&lt;a class="anchor" href="#01-03%e5%9f%ba%e7%a1%80%e9%85%8d%e7%bd%ae">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>16:04&lt;span style="color:#f92672">]&lt;/span> 01-欢迎来到 OpenGL-Welcome to OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>22:03&lt;span style="color:#f92672">]&lt;/span> 02-在 C++ 中设置 OpenGL 并创建窗口-Setting up OpenGL and Creating a Window in C++
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>18:21&lt;span style="color:#f92672">]&lt;/span> 03-在 C++ 中使用现代 OpenGL-Using Modern OpenGL in C++
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>20:06&lt;span style="color:#f92672">]&lt;/span> 04-顶点缓冲区与在 OpenGL 中绘制三角形-Vertex Buffers and Drawing a Triangle in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>18:54&lt;span style="color:#f92672">]&lt;/span> 05-OpenGL 中的顶点属性与布局-Vertex Attributes and Layouts in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>17:37&lt;span style="color:#f92672">]&lt;/span> 06-OpenGL 中的着色器工作原理-How Shaders Work in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>28:21&lt;span style="color:#f92672">]&lt;/span> 07-在 OpenGL 中编写着色器-Writing a Shader in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>21:15&lt;span style="color:#f92672">]&lt;/span> 08-我是如何处理 OpenGL 中的着色器的-How I Deal with Shaders in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>16:54&lt;span style="color:#f92672">]&lt;/span> 09-OpenGL 中的索引缓冲区-Index Buffers in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>23:42&lt;span style="color:#f92672">]&lt;/span> 10-处理 OpenGL 中的错误-Dealing with Errors in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>11:27&lt;span style="color:#f92672">]&lt;/span> 11-OpenGL 中的 Uniform 变量-Uniforms in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>21:50&lt;span style="color:#f92672">]&lt;/span> 12-OpenGL 中的顶点数组-Vertex Arrays in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>26:46&lt;span style="color:#f92672">]&lt;/span> 13-将 OpenGL 抽象为类-Abstracting OpenGL into Classes
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>30:07&lt;span style="color:#f92672">]&lt;/span> 14-OpenGL 中的缓冲区布局抽象-Buffer Layout Abstraction in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>21:56&lt;span style="color:#f92672">]&lt;/span> 15-OpenGL 中的着色器抽象-Shader Abstraction in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>14:43&lt;span style="color:#f92672">]&lt;/span> 16-在 OpenGL 中编写基础渲染器-Writing a Basic Renderer in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>31:44&lt;span style="color:#f92672">]&lt;/span> 17-OpenGL 中的纹理-Textures in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>12:37&lt;span style="color:#f92672">]&lt;/span> 18-OpenGL 中的混合-Blending in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>18:07&lt;span style="color:#f92672">]&lt;/span> 19-OpenGL 中的数学-Maths in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>20:10&lt;span style="color:#f92672">]&lt;/span> 20-OpenGL 中的投影矩阵-Projection Matrices in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>15:53&lt;span style="color:#f92672">]&lt;/span> 21-OpenGL 中的 MVP 矩阵-Model View Projection Matrices in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>14:36&lt;span style="color:#f92672">]&lt;/span> 22-在 OpenGL 中使用 ImGui-ImGui in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>12:21&lt;span style="color:#f92672">]&lt;/span> 23-在 OpenGL 中渲染多个物体-Rendering Multiple Objects in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>16:52&lt;span style="color:#f92672">]&lt;/span> 24-为 OpenGL 设置测试框架-Setting up a Test Framework &lt;span style="color:#66d9ef">for&lt;/span> OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>22:46&lt;span style="color:#f92672">]&lt;/span> 25-在 OpenGL 中创建测试-Creating Tests in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>28:13&lt;span style="color:#f92672">]&lt;/span> 26-在 OpenGL 中进行纹理测试-Creating a Texture Test in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>11:37&lt;span style="color:#f92672">]&lt;/span> 27-如何让你的 UNIFORMS 更快-How to make your UNIFORMS FASTER in OpenGL
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>12:25&lt;span style="color:#f92672">]&lt;/span> 28-批量渲染：简介-Batch Rendering - An Introduction
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>09:15&lt;span style="color:#f92672">]&lt;/span> 29-批量渲染：颜色-Batch Rendering - Colors
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>15:51&lt;span style="color:#f92672">]&lt;/span> 30-批量渲染：纹理-Batch Rendering - Textures
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">[&lt;/span>23:17&lt;span style="color:#f92672">]&lt;/span> 31-批量渲染：动态几何体-Batch Rendering - Dynamic Geometry&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="01welcomtoopengl">01WelcomToOpengl&lt;a class="anchor" href="#01welcomtoopengl">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>课程初衷与背景
&lt;ul>
&lt;li>作者介绍了为什么要制作这个系列：市面上很多教程只教“怎么做”，而不教“为什么”。&lt;/li>
&lt;li>本系列的目标是不仅让你写出代码，还要让你理解 OpenGL 的底层工作原理及其与 GPU 的交互逻辑。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>什么是 OpenGL？
&lt;ul>
&lt;li>&lt;mark>核心定义&lt;/mark>：OpenGL 本质上是一个&lt;mark>规范（Specification）&lt;/mark> &lt;del>接口，API&lt;/del> ，而不是一个具体的库。它&lt;mark>规定了函数应该如何命名、参数是什么以及预期的行为&lt;/mark>。 &lt;del>允许我们实际访问我们的GPU，GraphicsProcessingUnit，图形处理单元。OpenGL是其中之一的接口，还有Direct3D，Vulkan，Metal等&lt;/del>&lt;/li>
&lt;li>&lt;mark>实现者&lt;/mark>：&lt;em>具体的实现通常由显卡厂商（NVIDIA, AMD, Intel）编写在驱动程序中&lt;/em>。&lt;/li>
&lt;li>跨平台，Windows、Linux、Mac、Android、IOS&lt;/li>
&lt;li>&lt;mark>状态机（State Machine）&lt;/mark>：初步引入 &lt;mark>OpenGL 是一个状态机&lt;/mark>的概念，你&lt;mark>设置好状态（如颜色、缓冲区），然后发出指令进行渲染&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>现代 OpenGL vs 传统 OpenGL
&lt;ul>
&lt;li>&lt;mark>Legacy OpenGL (固定管线)&lt;/mark>：简单但不够灵活，很多功能已经废弃（如 &lt;code>glBegin&lt;/code>, &lt;code>glEnd&lt;/code>）。&lt;/li>
&lt;li>&lt;mark>Modern OpenGL (可编程管线)&lt;/mark>：通过 &lt;mark>着色器 (Shaders)&lt;/mark> 控制渲染过程。虽然代码量显著增加，但提供了&lt;mark>极大的灵活性和性能优化&lt;/mark>空间。&lt;/li>
&lt;li>Shader（着色器）是程序，在==&lt;em>GPU&lt;/em>==上运行的代码程序&lt;/li>
&lt;li>本系列将专注于 &lt;mark>Modern OpenGL (版本 3.3 及以上)&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>学习 OpenGL 的难点与心态
&lt;ul>
&lt;li>强调了学习曲线：初期需要写==大量的“模板代码”（Boilerplate code）==才能在屏幕上画出一个简单的三角形。&lt;/li>
&lt;li>&lt;mark>图形管线 (Graphics Pipeline)&lt;/mark>：解释了&lt;mark>数据如何从 CPU 传输到 GPU&lt;/mark>，并&lt;mark>经过顶点处理、光栅化最终变成像素&lt;/mark>的过程。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>开发环境与工具链预告
&lt;ul>
&lt;li>虽然是跨平台的，但本系列主要在 Windows 下使用 &lt;mark>Visual Studio&lt;/mark> 演示。&lt;/li>
&lt;li>提到后续会使用的关键第三方库：&lt;mark>GLFW&lt;/mark>（窗口管理）和 &lt;mark>GLEW/GLAD&lt;/mark>（访问 OpenGL 扩展函数）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>总结与后续计划
&lt;ul>
&lt;li>鼓励初学者不要被前几集的复杂配置和概念吓退。&lt;/li>
&lt;li>下一集将正式进入 C++ 环境配置，动手创建第一个窗口。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="02设置opengl和创建窗口">02设置Opengl和创建窗口&lt;a class="anchor" href="#02%e8%ae%be%e7%bd%aeopengl%e5%92%8c%e5%88%9b%e5%bb%ba%e7%aa%97%e5%8f%a3">#&lt;/a>&lt;/h1>
&lt;p>主要讲解如何在 Windows 环境下使用 Visual Studio 搭建 OpenGL 开发环境，并编写代码成功弹出一个窗口。这是所有图形编程的起点。&lt;/p></description></item><item><title>04HelloTriangle</title><link>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/learnopengl/01%E5%85%A5%E9%97%A8/04HelloTriangle/</link><pubDate>Sat, 14 Mar 2026 07:25:12 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/Opengl/learnopengl/01%E5%85%A5%E9%97%A8/04HelloTriangle/</guid><description>&lt;h1 id="你好三角">你好，三角&lt;a class="anchor" href="#%e4%bd%a0%e5%a5%bd%e4%b8%89%e8%a7%92">#&lt;/a>&lt;/h1>
&lt;p>在 OpenGL 中，所有物体都处于三维空间，但屏幕或窗口是一个二维像素数组，因此 &lt;mark>OpenGL 的大部分工作是将所有三维坐标转换为适合屏幕的二维像素&lt;/mark>。将三维坐标转换为二维像素的过程由 OpenGL 的*图形管线 &lt;del>graphics pipeline&lt;/del> *管理。图形管线可以分为两大部分：==第一部分将三维坐标转换为二维坐标，第二部分将二维坐标转换为实际的彩色像素 &lt;del>第二部分第一步：把由坐标定义的几何形状，切割成数以万计的待处理像素（片段）。第二步才是填充像素&lt;/del> ==。本章将简要讨论图形管线以及如何利用它来创建精美的像素。&lt;/p>
&lt;p>图形管线&lt;mark>以一组三维坐标作为输入，并将其转换为屏幕上的彩色二维像素&lt;/mark>。图形管线可以分为多个步骤，每个步骤都需要前一步的输出作为输入 &lt;del>串行，阶段性依赖&lt;/del> 。所有这些步骤都高度专业化（每个步骤都具有特定的功能），并且可以轻松地&lt;mark>并行&lt;/mark>执行 &lt;del>同一个步骤并行&lt;/del> 。由于其并行特性，&lt;mark>如今的显卡拥有数千个小型处理核心&lt;/mark>，以便在图形管线中快速处理数据。&lt;mark>这些处理核心在 GPU 上运行小型程序，用于执行管线的每个步骤&lt;/mark>。这些小型程序被称为&lt;mark>着色器&lt;/mark>。&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>&lt;del>并行还有另一个意思：当第一批顶点处理完进入“光栅化”车间时，顶点车间并不需要闲着。它可以立刻开始处理下一批模型或者下一帧的顶点&lt;/del>&lt;/p>&lt;/blockquote>&lt;p>&lt;mark>开发者可以配置部分着色器，从而编写自定义着色器来替换现有的默认着色器&lt;/mark>。这使我们能够对&lt;mark>渲染管线的特定部分进行更精细的控制&lt;/mark>，并且由于它们&lt;mark>运行在 GPU 上，因此还可以节省宝贵的 CPU 时间&lt;/mark>。着色器使用 &lt;mark>OpenGL 着色语言 (GLSL) ~~OpenGL Shading Language ~~&lt;/mark> 编写，我们将在下一章中深入探讨。&lt;/p>
&lt;p>下方是图形管线所有阶段的抽象表示。请注意，&lt;mark>蓝色部分表示我们可以注入自定义着色器&lt;/mark>的部分。&lt;/p>
&lt;p>&lt;img src="img/ly-20260314192652106.png" alt="" />&lt;/p>
&lt;p>&lt;em>&lt;mark>顶点着色器&lt;/mark>&lt;/em> &lt;del>把 3D 空间的坐标转换成屏幕上的 2D 坐标（术语叫标准化设备坐标）&lt;/del> -&amp;gt;&lt;em>几何着色器&lt;/em> &lt;del>增减图形：可以把一个点变成一个三角形，或者把一个三角形删掉。这里，几何着色器根据这 3 个点，计算出了第 4 个点的位置，并把它们重新组合。输出：它“发射”出了足够的顶点，组成了两个独立的三角形图元。&lt;/del> -&amp;gt;图元组装 &lt;del>把处理好的点“连线”&lt;/del> -&amp;gt;光栅化 &lt;del>计算这个三角形到底盖住了屏幕上哪些像素格子&lt;/del> -&amp;gt;&lt;em>&lt;mark>片段着色器&lt;/mark>&lt;/em> &lt;del>根据光照、纹理、材质，给这个像素算出一个最终的 RGBA 值&lt;/del> -&amp;gt;测试与混合 &lt;del>深度测试 (Depth Test)：检查这个像素是不是被别的物体挡住了。模板测试：一些特殊遮罩效果。混合 (Blending)：如果是半透明的，就把它和背景颜色融合&lt;/del>&lt;/p>
&lt;p>如您所见，图形管线包含大量模块 &lt;del>应该说的是这六个&lt;/del> ，每个模块负责&lt;mark>将顶点数据转换为完整渲染像素的特定 &lt;del>某个步骤&lt;/del> 步骤&lt;/mark>。我们将&lt;mark>以简化的方式简要解释管线的每个部分&lt;/mark>，以便您对管线的工作原理有一个大致的了解。&lt;/p>
&lt;p>作为图形管线的输入，我们传入一个名为 &lt;code>Vertex Data&lt;/code> 的数组，其中包含三个 3D 坐标，它们应该构成一个三角形；这个顶点数据是一个顶点集合。每个顶点都是一个包含 3D 坐标数据的集合。&lt;mark>顶点数据使用顶点属性&lt;/mark>来表示，这些属性可以包含我们想要的任何数据，但&lt;mark>为了简单起见，我们假设每个顶点仅包含一个 3D 位置和一个颜色值&lt;/mark>。&lt;/p></description></item><item><title>105弱指针</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/105%E5%BC%B1%E6%8C%87%E9%92%88/</link><pubDate>Wed, 11 Mar 2026 21:30:15 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/105%E5%BC%B1%E6%8C%87%E9%92%88/</guid><description>&lt;h1 id="共享指针与唯一指针例子">共享指针与唯一指针例子&lt;a class="anchor" href="#%e5%85%b1%e4%ba%ab%e6%8c%87%e9%92%88%e4%b8%8e%e5%94%af%e4%b8%80%e6%8c%87%e9%92%88%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP105
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity Created&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Entity() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity Destroyed&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// --- unique_ptr 示例 ---
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> e1 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>make_unique&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// std::unique_ptr&amp;lt;Entity&amp;gt; e2 = e1; // 错误！禁止复制
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> e2 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(e1); &lt;span style="color:#75715e">// 允许移动所有权，e1 现在为空
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	} &lt;span style="color:#75715e">// e2 离开作用域，Entity 在这里被销毁
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-----------------&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// --- shared_ptr 示例 ---
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>shared_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> sharedOuter;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//std::shared_ptr对象实例内部有一个引用计数，简单记录有多少个共享指针指向内部Entity对象的实例
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			std&lt;span style="color:#f92672">::&lt;/span>shared_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> sharedInner &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>make_shared&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			sharedOuter &lt;span style="color:#f92672">=&lt;/span> sharedInner; &lt;span style="color:#75715e">// 允许复制（拷贝赋值函数），引用计数变为 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Inner scope ending1...&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>shared_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> sharedInner1 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(sharedOuter);&lt;span style="color:#75715e">//这里把sharedInner的所有权移走了，计数减一，但是本身又导致计数加一，所以目前是2 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Inner scope ending2...&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		} &lt;span style="color:#75715e">// sharedInner1 离开作用域，sharedOuter所有权被移走，所以没有任何共享指针指向Entity了， Entity 被销毁 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Outer scope still holds Entity？&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} &lt;span style="color:#75715e">//作用域结束，sharedOuter 离开作用域，Entity 最终在这里被销毁
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity Created
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity Destroyed
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-----------------
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity Created
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Inner scope ending1...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Inner scope ending2...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity Destroyed
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Outer scope still holds Entity？
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>共享指针、强引用，能防止对象销毁，也被称作具名引用。即他们对一个对象各自都拥有所有权&lt;/p></description></item><item><title>100cpp映射容器</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/100cpp%E6%98%A0%E5%B0%84%E5%AE%B9%E5%99%A8/</link><pubDate>Wed, 11 Mar 2026 16:22:01 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/100cpp%E6%98%A0%E5%B0%84%E5%AE%B9%E5%99%A8/</guid><description>&lt;h1 id="简介">简介&lt;a class="anchor" href="#%e7%ae%80%e4%bb%8b">#&lt;/a>&lt;/h1>
&lt;h2 id="什么是-map">什么是 Map？&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af-map">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>Map 是一种容器，用于存储&lt;mark>键值对&lt;/mark>。它允许你通过一个“键”（Key）来快速查找对应的“值”（Value）。&lt;/li>
&lt;li>类比：就像一本字典，单词是键，定义是值。&lt;/li>
&lt;/ul>
&lt;h2 id="stdmap-vs-stdunordered_map">std::map vs std::unordered_map&lt;a class="anchor" href="#stdmap-vs-stdunordered_map">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>std::map (&lt;mark>有序&lt;/mark>映射)：
&lt;ul>
&lt;li>底层结构：红黑树（一种自平衡二叉搜索树）。&lt;/li>
&lt;li>特点：元素按键的顺序自动排序。&lt;/li>
&lt;li>复杂度：&lt;mark>查找、插入、删除均为 O(logn)&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>std::unordered_map (无序映射)：
&lt;ul>
&lt;li>底层结构：哈希表（Hash Table）。&lt;/li>
&lt;li>特点：&lt;mark>元素没有特定顺序&lt;/mark>。&lt;/li>
&lt;li>复杂度：&lt;mark>平均情况下查找速度为 O(1)&lt;/mark>，通常比 &lt;code>std::map&lt;/code> 快，除非哈希冲突严重。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="代码演示基础用法">代码演示：基础用法&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e6%bc%94%e7%a4%ba%e5%9f%ba%e7%a1%80%e7%94%a8%e6%b3%95">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>展示如何定义 &lt;code>std::map&amp;lt;std::string, CityRecord&amp;gt;&lt;/code>。&lt;/li>
&lt;li>使用 &lt;code>operator[]&lt;/code> 进行赋值：&lt;code>map[&amp;quot;Berlin&amp;quot;] = CityRecord { ... };&lt;/code>。&lt;/li>
&lt;li>注意：如果访问一个不存在的键，&lt;code>operator[]&lt;/code> 会自动创建一个默认构造的对象并插入。&lt;/li>
&lt;/ul>
&lt;h2 id="迭代与访问">迭代与访问&lt;a class="anchor" href="#%e8%bf%ad%e4%bb%a3%e4%b8%8e%e8%ae%bf%e9%97%ae">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>演示如何使用 &lt;code>for (auto&amp;amp; [key, value] : map)&lt;/code>（C++17 结构化绑定）遍历 Map。&lt;/li>
&lt;li>解释了老式迭代器用法：&lt;code>it-&amp;gt;first&lt;/code> 是键，&lt;code>it-&amp;gt;second&lt;/code> 是值。&lt;/li>
&lt;/ul>
&lt;h2 id="性能取舍与选择建议">性能取舍与选择建议&lt;a class="anchor" href="#%e6%80%a7%e8%83%bd%e5%8f%96%e8%88%8d%e4%b8%8e%e9%80%89%e6%8b%a9%e5%bb%ba%e8%ae%ae">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>优先选择 &lt;code>std::unordered_map&lt;/code>：如果你只需要快速查找，不需要元素有序，那么无序映射通常性能更优。&lt;/li>
&lt;li>选择 &lt;code>std::map&lt;/code> 的场景：当你需要遍历时保持特定顺序，或者需要使用类似 &lt;code>lower_bound&lt;/code> 的区间查找功能时。&lt;/li>
&lt;/ul>
&lt;h2 id="复杂键的处理">复杂键的处理&lt;a class="anchor" href="#%e5%a4%8d%e6%9d%82%e9%94%ae%e7%9a%84%e5%a4%84%e7%90%86">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>讲解了如果使用自定义类作为键，&lt;code>std::map&lt;/code> 需要该类重载 &lt;code>&amp;lt;&lt;/code> 运算符，而 &lt;code>std::unordered_map&lt;/code> 则需要提供哈希函数。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP100
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;map&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;unordered_map&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">CityRecord&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">uint64_t&lt;/span> Population;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">double&lt;/span> Latitude, Longitude;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> CityRecord&lt;span style="color:#f92672">&amp;amp;&lt;/span> cityRecord)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Name: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> cityRecord.Name &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Population: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> cityRecord.Population &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Latitude: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> cityRecord.Latitude &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Longitude: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> cityRecord.Longitude &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> stream;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> std {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">hash&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>CityRecord&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		size_t &lt;span style="color:#a6e22e">operator&lt;/span>()(&lt;span style="color:#66d9ef">const&lt;/span> CityRecord&lt;span style="color:#f92672">&amp;amp;&lt;/span> key)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//hash&amp;lt;std::string&amp;gt;()这是调用构造函数，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//然后构造了std::hash&amp;lt;CityRecord&amp;gt; 类型的对象，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//之后调用了该对象的()重载方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#66d9ef">return&lt;/span> hash&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span>()(key.Name);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//计算City
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	CityRecord cityRecord &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#e6db74">&amp;#34;name1&amp;#34;&lt;/span>,&lt;span style="color:#ae81ff">10000&lt;/span>,&lt;span style="color:#ae81ff">2.3&lt;/span>,&lt;span style="color:#ae81ff">4.5&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">auto&lt;/span> hashcode&lt;span style="color:#f92672">=&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>hash&lt;span style="color:#f92672">&amp;lt;&lt;/span>CityRecord&lt;span style="color:#f92672">&amp;gt;&lt;/span>()(cityRecord);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (hashcode)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hashcode: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> hashcode &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> cityRecord &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="模板特化">模板特化&lt;a class="anchor" href="#%e6%a8%a1%e6%9d%bf%e7%89%b9%e5%8c%96">#&lt;/a>&lt;/h3>
&lt;h4 id="1-什么是普通模板工厂的模具">1. 什么是普通模板？（工厂的模具）&lt;a class="anchor" href="#1-%e4%bb%80%e4%b9%88%e6%98%af%e6%99%ae%e9%80%9a%e6%a8%a1%e6%9d%bf%e5%b7%a5%e5%8e%82%e7%9a%84%e6%a8%a1%e5%85%b7">#&lt;/a>&lt;/h4>
&lt;p>模板就像一个&lt;mark>通用的模具&lt;/mark>。比如你想写一个 &lt;code>print&lt;/code> 函数，不管是 &lt;code>int&lt;/code>、&lt;code>float&lt;/code> 还是 &lt;code>string&lt;/code> 都能用：&lt;/p></description></item><item><title>102如何正确搭建cpp项目</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/102%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E6%90%AD%E5%BB%BAcpp%E9%A1%B9%E7%9B%AE/</link><pubDate>Wed, 11 Mar 2026 15:46:26 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/102%E5%A6%82%E4%BD%95%E6%AD%A3%E7%A1%AE%E6%90%AD%E5%BB%BAcpp%E9%A1%B9%E7%9B%AE/</guid><description>&lt;h1 id="创建项目并克隆">创建项目并克隆&lt;a class="anchor" href="#%e5%88%9b%e5%bb%ba%e9%a1%b9%e7%9b%ae%e5%b9%b6%e5%85%8b%e9%9a%86">#&lt;/a>&lt;/h1>
&lt;p>&lt;code>https://github.com/TheCherno/ProjectTemplate&lt;/code> ，到这个地址 UseThisTemplate -&amp;gt; CreateNewRepository&lt;/p>
&lt;p>在本地windows克隆下来&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>git clone git@github.com:lwmfjc/ChernoTemplateProject.git&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>之后我把项目删掉.git文件夹后放到了另一个自己的备份gitRepository中&lt;/p>
&lt;h1 id="使用">使用&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8">#&lt;/a>&lt;/h1>
&lt;p>双击Setup-Windows.bat 运行&lt;/p>
&lt;p>&lt;img src="img/ly-20260311155909650.png" alt="" />&lt;/p>
&lt;p>在visual studio中，File-Open-Solution，选择 NewProject.sln&lt;/p>
&lt;p>打开之后直接F5运行&lt;/p>
&lt;p>&lt;img src="img/ly-20260311160204390.png" alt="" />&lt;/p>
&lt;p>==这集先跳过，貌似有点不太常用 &lt;del>注：看到00:07:34&lt;/del> ==&lt;/p></description></item><item><title>95如何真正学好cpp</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/95%E5%A6%82%E4%BD%95%E7%9C%9F%E6%AD%A3%E5%AD%A6%E5%A5%BDcpp/</link><pubDate>Wed, 11 Mar 2026 09:32:28 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/95%E5%A6%82%E4%BD%95%E7%9C%9F%E6%AD%A3%E5%AD%A6%E5%A5%BDcpp/</guid><description>&lt;h1 id="核心问题学完基础后该做什么">核心问题：学完基础后该做什么？&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e9%97%ae%e9%a2%98%e5%ad%a6%e5%ae%8c%e5%9f%ba%e7%a1%80%e5%90%8e%e8%af%a5%e5%81%9a%e4%bb%80%e4%b9%88">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>现状：许多人看完了视频、读完了教科书、甚至通过了大学考试，但依然觉得不会自由地编写代码，无法“流利”地使用 C++。&lt;/li>
&lt;li>核心建议：沉浸在开源项目（Open Source Projects）中。&lt;/li>
&lt;/ul>
&lt;h1 id="真实世界的代码-vs-教科书">真实世界的代码 vs. 教科书&lt;a class="anchor" href="#%e7%9c%9f%e5%ae%9e%e4%b8%96%e7%95%8c%e7%9a%84%e4%bb%a3%e7%a0%81-vs-%e6%95%99%e7%a7%91%e4%b9%a6">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>差异：教科书和作业里的代码（如实现一个 Vector 或 List）是教学性质的，而现实世界的代码规模更大、逻辑更复杂。&lt;/li>
&lt;li>面试视角：雇主想看到的是你理解软件是如何构建的，以及你是否见过并能处理真实代码库中的复杂性。&lt;/li>
&lt;/ul>
&lt;h1 id="语言学习的类比">“语言学习”的类比&lt;a class="anchor" href="#%e8%af%ad%e8%a8%80%e5%ad%a6%e4%b9%a0%e7%9a%84%e7%b1%bb%e6%af%94">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>学习环境：学习编程就像学外语（德语或日语）。只看语法书和做练习是不够的，你必须开始看电视、电影，甚至搬到那个国家居住。&lt;/li>
&lt;li>编程沉浸：对于 C++，这意味着你需要阅读、运行并尝试修改别人的代码，让自己置身于那个语言环境中。&lt;/li>
&lt;/ul>
&lt;h1 id="如何开始选择你感兴趣的项目">如何开始？选择你感兴趣的项目&lt;a class="anchor" href="#%e5%a6%82%e4%bd%95%e5%bc%80%e5%a7%8b%e9%80%89%e6%8b%a9%e4%bd%a0%e6%84%9f%e5%85%b4%e8%b6%a3%e7%9a%84%e9%a1%b9%e7%9b%ae">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>兴趣导向：
&lt;ul>
&lt;li>喜欢游戏？去 GitHub 找简单的开源游戏（如 Mario 克隆版或 80 年代街机游戏）。&lt;/li>
&lt;li>喜欢引擎？研究 Unreal Engine、Godot 或 Cherno 自己的 Hazel 引擎。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Bug 赏金计划 ：参与寻找 C++ 代码中的 bug，这不仅能锻炼能力，有时还能获得报酬。&lt;/li>
&lt;/ul>
&lt;h1 id="什么时候可以开始沉浸">什么时候可以开始“沉浸”？&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%97%b6%e5%80%99%e5%8f%af%e4%bb%a5%e5%bc%80%e5%a7%8b%e6%b2%89%e6%b5%b8">#&lt;/a>&lt;/h1>
&lt;p>结论：随时。 即使你觉得还太早，也不必担心。就像没学多少日语就去日本一样，虽然痛苦，但那是进步最快的方式。&lt;/p>
&lt;h1 id="实战演示分析-opencv-源码">实战演示：分析 OpenCV 源码&lt;a class="anchor" href="#%e5%ae%9e%e6%88%98%e6%bc%94%e7%a4%ba%e5%88%86%e6%9e%90-opencv-%e6%ba%90%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>流程：从 GitHub 克隆项目 -&amp;gt; 使用 CMake 生成 VS 工程 -&amp;gt; 编译并运行。&lt;/li>
&lt;li>工具辅助（PVS-Studio） ：Cherno 演示了使用静态分析工具查看 OpenCV 源码中的潜在错误。&lt;/li>
&lt;li>学习点 ：例如通过分析宏定义中的 if 语句冗余问题，你可以学到更深层的编码经验，这些是只看语法书学不到的。&lt;/li>
&lt;/ul>
&lt;h1 id="总结超越代码本身的收获">总结：超越代码本身的收获&lt;a class="anchor" href="#%e6%80%bb%e7%bb%93%e8%b6%85%e8%b6%8a%e4%bb%a3%e7%a0%81%e6%9c%ac%e8%ba%ab%e7%9a%84%e6%94%b6%e8%8e%b7">#&lt;/a>&lt;/h1>
&lt;p>通过阅读开源项目，你不仅学会了写 C++，还学会了：&lt;/p></description></item><item><title>94编写迭代器</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/94%E7%BC%96%E5%86%99%E8%BF%AD%E4%BB%A3%E5%99%A8/</link><pubDate>Tue, 10 Mar 2026 12:59:30 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/94%E7%BC%96%E5%86%99%E8%BF%AD%E4%BB%A3%E5%99%A8/</guid><description>&lt;ul>
&lt;li>迭代器是用来遍历&lt;mark>某种数据结构&lt;/mark>的容器的&lt;/li>
&lt;li>迭代器统一了接口，所以通过同样的接口不同的实现来迭代不同的容器&lt;/li>
&lt;li>迭代器：记录一个指针，然后遍历就像移动指针一样，直到末尾&lt;/li>
&lt;/ul>
&lt;h1 id="vector类">Vector类&lt;a class="anchor" href="#vector%e7%b1%bb">#&lt;/a>&lt;/h1>
&lt;p>为Vector添加部分代码&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Vector&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Vector的值类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> ValueType &lt;span style="color:#f92672">=&lt;/span> T;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//public 类型别名 (using/typedef)：属于类（Class/Type）。它是一个“类型标签”，就像 Vector&amp;lt;int&amp;gt; 内部定义的一个子类型。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> Iterator &lt;span style="color:#f92672">=&lt;/span> VectorIterator&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>T&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Iterator &lt;span style="color:#a6e22e">begin&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Iterator(m_Data);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Iterator &lt;span style="color:#a6e22e">end&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Iterator(m_Data &lt;span style="color:#f92672">+&lt;/span> m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>Vector类完整代码&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP94
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//为某种类型(Vector)写迭代器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> Vector&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">VectorIterator&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Vector的值的类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> ValueType &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">typename&lt;/span> Vector&lt;span style="color:#f92672">::&lt;/span>ValueType;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">using&lt;/span> PointerType &lt;span style="color:#f92672">=&lt;/span> ValueType&lt;span style="color:#f92672">*&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">using&lt;/span> ReferenceType &lt;span style="color:#f92672">=&lt;/span> ValueType&lt;span style="color:#f92672">&amp;amp;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	VectorIterator(PointerType ptr)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Ptr(ptr)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//前缀运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	VectorIterator&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">++&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Ptr&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//前缀运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	VectorIterator&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">--&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Ptr&lt;span style="color:#f92672">--&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//后缀运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//编译器用来区分前缀和后缀的唯一手段，int
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//是语法占位符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	VectorIterator&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">++&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//这里是复制，由于成员只有一个指针，代价可以接受
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		VectorIterator iterator &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//前缀运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#f92672">++&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> iterator;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//后缀运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	VectorIterator&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">--&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//这里是复制，由于成员只有一个指针，代价可以接受
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		VectorIterator iterator &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//前缀运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#f92672">--&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> iterator;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ReferenceType &lt;span style="color:#66d9ef">operator&lt;/span>[](&lt;span style="color:#66d9ef">int&lt;/span> index)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>(m_Ptr &lt;span style="color:#f92672">+&lt;/span> index);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//C++ 对 -&amp;gt; 有特殊处理。当你使用 it-&amp;gt;Method() 时，它会调用 it.operator-&amp;gt;() 得到 m_Ptr，然后再次对结果应用 -&amp;gt;。所以最终执行的是 m_Ptr-&amp;gt;Method()。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//所以这里需要返回一个指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	PointerType &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Ptr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ReferenceType &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">*&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>m_Ptr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">==&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> VectorIterator&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Ptr &lt;span style="color:#f92672">==&lt;/span> other.m_Ptr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">!=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> VectorIterator&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">!&lt;/span>(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">==&lt;/span> other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PointerType m_Ptr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Vector&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Vector的值类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> ValueType &lt;span style="color:#f92672">=&lt;/span> T;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//public 类型别名 (using/typedef)：属于类（Class/Type）。它是一个“类型标签”，就像 Vector&amp;lt;int&amp;gt; 内部定义的一个子类型。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> Iterator &lt;span style="color:#f92672">=&lt;/span> VectorIterator&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>T&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Iterator &lt;span style="color:#a6e22e">begin&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Iterator(m_Data);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Iterator &lt;span style="color:#a6e22e">end&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Iterator(m_Data &lt;span style="color:#f92672">+&lt;/span> m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//allocate 2 elements
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ReAlloc(&lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====构造器中初始化容量2======&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PushBack&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">&amp;amp;&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//如果当前数量量已经大于等于容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_Size &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Capacity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//如果增长，容量扩大为1.5倍
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ReAlloc(m_Capacity &lt;span style="color:#f92672">+&lt;/span> m_Capacity &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//m_Data[m_Size] 是一个已经存在的对象，所以
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//这里调用的是拷贝赋值函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//m_Data[m_Size] = value;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// new (&amp;amp;地址) 类型(参数)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">new&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>m_Data[m_Size]) T(value);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Size&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;添加元素:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==================&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//1. PushBack的push右值引用的版本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. value 的类型始终是 Vector3&amp;amp;&amp;amp;（右值引用），
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 但它在函数体内的表现（属性）是一个左值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PushBack&lt;/span>(T&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//如果当前数量量已经大于等于容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_Size &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Capacity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//如果增长，容量扩大为1.5倍
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ReAlloc(m_Capacity &lt;span style="color:#f92672">+&lt;/span> m_Capacity &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. m_Data[m_Size] 是一个已经存在的对象，所以
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//这里调用的是移动赋值函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. value 传入时是右值引用，但在函数内部它有了名
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 字，就变成了左值。为了触发移动赋值，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 必须用 std::move 把它重新转回右值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//3. 如果没有移动赋值函数，会去调用拷贝赋值函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//m_Data[m_Size] = std::move(value);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 使用移动构造函数在原始内存上创建对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">new&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>m_Data[m_Size]) T(std&lt;span style="color:#f92672">::&lt;/span>move(value));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Size&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;添加元素:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==================&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//变长参数模板，三个点 ... 表示它可以接收
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 任意数量、任意类型的参数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span>... Args&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//&amp;amp;&amp;amp; 配合模板参数 Args 使用时，不再仅仅是
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 右值引用，它被称为万能引用，既能接收左值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// ，也能接收右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	T&lt;span style="color:#f92672">&amp;amp;&lt;/span> EmplaceBack(Args&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>... args)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//如果当前数量量已经大于等于容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_Size &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Capacity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//如果增长，容量扩大为1.5倍
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ReAlloc(m_Capacity &lt;span style="color:#f92672">+&lt;/span> m_Capacity &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 参数一旦有了名字 args，它在函数内部就会变成左值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. 解决：std::forward 的作用是：如果你传进来时是右值，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 它就把它恢复成右值；如果你传进来时是左值，它就保持左
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//3. T(std::forward&amp;lt;Args&amp;gt;(args)...)这个是右值，调用移动
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 赋值函数后，马上destroy了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//m_Data[m_Size] = T(std::forward&amp;lt;Args&amp;gt;(args)...); 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//使用placement new运算符，原地构造，就不会有对临时对象move以及destroy的操作了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">new&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>m_Data[m_Size]) T(std&lt;span style="color:#f92672">::&lt;/span>forward&lt;span style="color:#f92672">&amp;lt;&lt;/span>Args&lt;span style="color:#f92672">&amp;gt;&lt;/span>(args)...);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;添加元素:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> m_Data[m_Size] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==================&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 取值（Evaluate）：首先取出 m_Size 当前的值（比如现在是 0）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. 定位（Access）：利用这个旧值 0 找到 m_Data[0] 的引用，作为函数的返回值准备好。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//3. 自增（Increment）：在这一行语句的逻辑完成，“返回”动作即将发生前（但还在函数体内），将 m_Size 的值加 1 变成 1。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[m_Size&lt;span style="color:#f92672">++&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PopBack&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_Size &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Size&lt;span style="color:#f92672">--&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//手动调用析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			m_Data[m_Size].&lt;span style="color:#f92672">~&lt;/span>T();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Clear&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data[i].&lt;span style="color:#f92672">~&lt;/span>T();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[](size_t index)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//assert
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[](size_t index) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//assert被设计为一种调试期工具,在发布版本会被去掉
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//assert
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	size_t &lt;span style="color:#a6e22e">Size&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Size; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Vector()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//会依次调用m_Data指向的所有对象的析构函数（
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 但是PopBack及Clear()已经调用过并已经释放了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// Vector3的m_MemoryBlock
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Clear();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//		delete[] m_Data;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#66d9ef">delete&lt;/span>(m_Data, m_Capacity &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(T));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> ReAlloc(size_t newCapacity) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 1. allocate a new block of memory
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 2. copy/move old elements into new block
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 3. delete
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 尽可能低层次的访问内存，而不是智能指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. 在堆上申请了一块连续(物理连续)的内存空间
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//3. 在堆上创建了 newCapacity 个对象，并调用了它们
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//的默认构造函数。也就是说，此时内存里已经存在了一
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//堆“空”的 Vector3 对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//T* newBlock = new T[newCapacity];
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//分配原始字节内存，不调用任何构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		T&lt;span style="color:#f92672">*&lt;/span> newBlock &lt;span style="color:#f92672">=&lt;/span> (T&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span>(newCapacity &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(T));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//如果新容量小于当前大小，即缩小容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (newCapacity &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 当前大小设置为新容量大小
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			m_Size &lt;span style="color:#f92672">=&lt;/span> newCapacity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;缩小容量--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;增大容量--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> m_Capacity &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-&amp;gt;&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> newCapacity &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//不会触发复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//memcpy(newBlock, m_Data, i * sizeof(T);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//复制,会触发复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//newBlock[i] = std::move(m_Data[i]);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 在 newBlock 的位置上，“构造”一个新对象，其内容移动自旧对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#66d9ef">new&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>newBlock[i]) T(std&lt;span style="color:#f92672">::&lt;/span>move(m_Data[i]));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//手动释放原来的对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data[i].&lt;span style="color:#f92672">~&lt;/span>T();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 逐一析构：编译器会根据该内存块记录的大小信息（通常存储在数组头部的隐藏偏移量中），从后往前（或从前往后，取决于实现）调用每一个 Vector3 对象的析构函数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. 释放内存：在所有对象的析构函数执行完毕后，才会一次性将整块堆内存归还给操作系统。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//delete[] m_Data;//释放原来指向的内存块
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#66d9ef">delete&lt;/span>(m_Data, m_Capacity &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(T));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//delete m_Data;只会触发第一个元素的析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> newBlock;&lt;span style="color:#75715e">//指向新的那个内存块
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Capacity &lt;span style="color:#f92672">=&lt;/span> newCapacity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">*&lt;/span> m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//实际数组个数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	size_t m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//可分配存储的元素个数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	size_t m_Capacity &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="main使用">Main使用&lt;a class="anchor" href="#main%e4%bd%bf%e7%94%a8">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP94
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;94_01_vector.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> values;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	values.EmplaceBack(&lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	values.EmplaceBack(&lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	values.EmplaceBack(&lt;span style="color:#ae81ff">3&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	values.EmplaceBack(&lt;span style="color:#ae81ff">4&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	values.EmplaceBack(&lt;span style="color:#ae81ff">5&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Not using iterators:&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> values.Size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> values[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Range-based for loop&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> value : values)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Iterator:&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;::&lt;/span>Iterator it &lt;span style="color:#f92672">=&lt;/span> values.begin();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		it &lt;span style="color:#f92672">!=&lt;/span> values.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>it &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>92动态数组实现</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/92%E5%8A%A8%E6%80%81%E6%95%B0%E7%BB%84%E5%AE%9E%E7%8E%B0/</link><pubDate>Mon, 09 Mar 2026 13:03:14 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/92%E5%8A%A8%E6%80%81%E6%95%B0%E7%BB%84%E5%AE%9E%E7%8E%B0/</guid><description>&lt;p>涉及到了&lt;mark>手动内存管理&lt;/mark>、&lt;mark>堆分配&lt;/mark>以及&lt;mark>模板类&lt;/mark>的深层逻辑。&lt;/p>
&lt;h1 id="简要概述">简要概述&lt;a class="anchor" href="#%e7%ae%80%e8%a6%81%e6%a6%82%e8%bf%b0">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>核心目标：实现动态扩容&lt;/mark>
&lt;ul>
&lt;li>作者明确了本集的目标：创建一个可以根据需要自动增长内存空间的容器，模拟 &lt;code>std::vector&lt;/code> 的核心行为。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>成员变量的改变：从栈到堆&lt;/mark>
&lt;ul>
&lt;li>不再使用 &lt;code>T m_Data[S]&lt;/code>，而是改为 &lt;code>T* m_Data&lt;/code> 指针。&lt;/li>
&lt;li>引入两个关键计数器：&lt;code>m_Size&lt;/code>（当前元素个数）和 &lt;code>m_Capacity&lt;/code>（当前分配的总空间）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>构造函数与析构函数&lt;/mark>
&lt;ul>
&lt;li>在构造函数中&lt;mark>预分配一小块初始内存&lt;/mark>。&lt;/li>
&lt;li>强调了&lt;mark>析构函数&lt;/mark>的重要性：必须使用 &lt;code>delete[] m_Data&lt;/code> 释放堆内存，否则会导致内存泄漏。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>实现 &lt;code>PushBack&lt;/code> 方法（核心逻辑）&lt;/mark>
&lt;ul>
&lt;li>这是本集最精彩的部分：当 &lt;code>m_Size &amp;gt;= m_Capacity&lt;/code> 时，触发“&lt;mark>重新分配（Reallocation）&lt;/mark>”。&lt;/li>
&lt;li>&lt;mark>扩容策略&lt;/mark>：作者演示了将容量翻倍（&lt;code>m_Capacity * 2&lt;/code>）的常用工程策略。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>手动执行内存迁移&lt;/mark>
&lt;ul>
&lt;li>详细步骤：申请一块更大的新内存 -&amp;gt; 将旧数据拷贝到新内存 -&amp;gt; 释放旧内存 -&amp;gt; 指针重定向。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>模板化的挑战&lt;/mark>
&lt;ul>
&lt;li>讨论了为什么 Vector 需要模板化，以及在&lt;mark>处理非简单类型（如 &lt;code>std::string&lt;/code>）时，简单的拷贝可能会失效&lt;/mark>（引出对后续移动语义的思考）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>性能测试与优化预告&lt;/mark>
&lt;ul>
&lt;li>对比了自定义 Vector 与标准库 &lt;code>std::vector&lt;/code> 的性能。&lt;/li>
&lt;li>提到目前的实现虽然可用，但频繁的拷贝开销巨大，引出后续关于 &lt;code>emplace_back&lt;/code> 的话题。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="代码vectorh">代码&lt;code>vector.h&lt;/code>&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81vectorh">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//91_01_vector.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP92
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Vector&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//allocate 2 elements
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ReAlloc(&lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====构造器中初始化容量2======&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PushBack&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">&amp;amp;&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//如果当前数量量已经大于等于容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_Size &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Capacity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//如果增长，容量扩大为1.5倍
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ReAlloc(m_Capacity &lt;span style="color:#f92672">+&lt;/span> m_Capacity &lt;span style="color:#f92672">/&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//m_Data[m_Size] 是一个已经存在的对象，所以
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//这里调用的是拷贝赋值函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Data[m_Size] &lt;span style="color:#f92672">=&lt;/span> value;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Size&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;添加元素:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==================&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[](size_t index)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//assert
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[](size_t index) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (index &lt;span style="color:#f92672">&amp;gt;=&lt;/span> m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//assert被设计为一种调试期工具,在发布版本会被去掉
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//assert
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	size_t &lt;span style="color:#a6e22e">Size&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Size; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Vector()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data; 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> ReAlloc(size_t newCapacity) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 1. allocate a new block of memory
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 2. copy/move old elements into new block
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 3. delete
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 尽可能低层次的访问内存，而不是智能指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. 在堆上申请了一块连续(物理连续)的内存空间
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//3. 在堆上创建了 newCapacity 个对象，并调用了它们
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//的默认构造函数。也就是说，此时内存里已经存在了一
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//堆“空”的 Vector3 对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		T&lt;span style="color:#f92672">*&lt;/span> newBlock &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> T[newCapacity];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//如果新容量小于当前大小，即缩小容量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (newCapacity &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 当前大小设置为新容量大小
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			m_Size &lt;span style="color:#f92672">=&lt;/span> newCapacity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;缩小容量--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;增大容量--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> m_Capacity &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-&amp;gt;&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> newCapacity &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//不会触发复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//memcpy(newBlock, m_Data, i * sizeof(T);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//复制,会触发复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			newBlock[i] &lt;span style="color:#f92672">=&lt;/span> m_Data[i];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 逐一析构：编译器会根据该内存块记录的大小信息（通常存储在数组头部的隐藏偏移量中），从后往前（或从前往后，取决于实现）调用每一个 Vector3 对象的析构函数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. 释放内存：在所有对象的析构函数执行完毕后，才会一次性将整块堆内存归还给操作系统。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;&lt;span style="color:#75715e">//释放原来指向的内存块
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//delete m_Data;只会触发第一个元素的析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> newBlock;&lt;span style="color:#75715e">//指向新的那个内存块
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Capacity &lt;span style="color:#f92672">=&lt;/span> newCapacity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">*&lt;/span> m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//实际数组个数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	size_t m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//可分配存储的元素个数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	size_t m_Capacity &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="应用添加stdstring元素">应用：添加&lt;code>std::string&lt;/code>元素&lt;a class="anchor" href="#%e5%ba%94%e7%94%a8%e6%b7%bb%e5%8a%a0stdstring%e5%85%83%e7%b4%a0">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP92
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//在堆上分配内存，创建动态数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//需要一个指向堆分配内存(数据缓冲区)的指针,随着不断
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//添加，当元素越来越多会达到临界点，没有足够空间存储新元素时，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//分配一个新的内存块使它有足够空间容纳这个新元素，将内存块中所有元素
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//复制到新内存块，然后删除旧内存块
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;92_01_vector.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> PrintVector(&lt;span style="color:#66d9ef">const&lt;/span> Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>T&lt;span style="color:#f92672">&amp;gt;&amp;amp;&lt;/span> vector)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> vector.Size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vector[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==================&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> vector;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;C++&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector01&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector02&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector03&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector04&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector05&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector06&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(&lt;span style="color:#e6db74">&amp;#34;Vector07&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintVector(vector);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--0-&amp;gt;2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====构造器中初始化容量2======
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:C++
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--2-&amp;gt;3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector01
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--3-&amp;gt;4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector02
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--4-&amp;gt;6
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector03
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector04
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--6-&amp;gt;9
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector05
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector06
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:Vector07
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">C++
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector01
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector02
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector03
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector04
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector05
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector06
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Vector07
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="应用添加自定义类元素">应用添加自定义类元素&lt;a class="anchor" href="#%e5%ba%94%e7%94%a8%e6%b7%bb%e5%8a%a0%e8%87%aa%e5%ae%9a%e4%b9%89%e7%b1%bb%e5%85%83%e7%b4%a0">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP92
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;92_01_vector.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>, y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>, z &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector3() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector3(&lt;span style="color:#66d9ef">float&lt;/span> scalar)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span> x(scalar), y(scalar), z(scalar) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector3(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y, &lt;span style="color:#66d9ef">float&lt;/span> z)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span> x(x), y(y), z(z) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 拷贝构造函数 (Copy Constructor)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vector3(&lt;span style="color:#66d9ef">const&lt;/span> Vector3&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span> x(other.x), y(other.y), z(other.z)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Copy&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//移动构造函数 (move Constructor)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vector3(Vector3&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span> x(other.x), y(other.y), z(other.z)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Move&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//拷贝赋值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vector3&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector3&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;copy=&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		x &lt;span style="color:#f92672">=&lt;/span> other.x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		y &lt;span style="color:#f92672">=&lt;/span> other.y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		z &lt;span style="color:#f92672">=&lt;/span> other.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//移动赋值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vector3&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(Vector3&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;move=&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		x &lt;span style="color:#f92672">=&lt;/span> other.x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		y &lt;span style="color:#f92672">=&lt;/span> other.y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		z &lt;span style="color:#f92672">=&lt;/span> other.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Vector3()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroy&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//全局重载函数，C++ 规定：对于二元运算符（有两个操作数的运算符），如果写成全局函数，第一个参数对应运算符左边的对象，第二个参数对应右边的对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream, &lt;span style="color:#66d9ef">const&lt;/span> Vector3&lt;span style="color:#f92672">&amp;amp;&lt;/span> v)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	stream &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> stream;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintVector&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vector3&lt;span style="color:#f92672">&amp;gt;&amp;amp;&lt;/span> vector)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> vector.Size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vector[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==================&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vector3&lt;span style="color:#f92672">&amp;gt;&lt;/span> vector;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Vector3(1.0f)-&amp;gt;创建一个匿名临时对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//临时对象会在包含它的那个“完整表达式（Full-expression）”结束时被销毁。即这行代码结束后该临时对象被析构
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vector.PushBack(Vector3(&lt;span style="color:#ae81ff">1.0f&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(Vector3{ &lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span>,&lt;span style="color:#ae81ff">4&lt;/span> });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vector.PushBack(Vector3{});
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintVector(vector);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--0-&amp;gt;2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====构造器中初始化容量2======
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copy=
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:1, 1, 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copy=
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:2, 3, 4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">增大容量--2-&amp;gt;3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copy=
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copy=
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copy=
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">添加元素:0, 0, 0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">1, 1, 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">2, 3, 4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0, 0, 0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==================
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如上，每次添加元素，以及扩容时的搬运原元素，都触发了复制赋值函数&lt;/p></description></item><item><title>91静态数组实现</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/91%E9%9D%99%E6%80%81%E6%95%B0%E7%BB%84%E5%AE%9E%E7%8E%B0/</link><pubDate>Sun, 08 Mar 2026 23:11:54 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/91%E9%9D%99%E6%80%81%E6%95%B0%E7%BB%84%E5%AE%9E%E7%8E%B0/</guid><description>&lt;ul>
&lt;li>&lt;mark>为什么要手写数据结构？&lt;/mark>
&lt;ul>
&lt;li>作者解释说，虽然 &lt;code>std::array&lt;/code> 很好用，但作为底层程序员，你应该了解它在&lt;mark>堆栈（Stack）&lt;mark>上是如何分配内存的。这有助于你&lt;/mark>理解内存布局和模板编程&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>模板类（Template Class）的声明&lt;/mark>
&lt;ul>
&lt;li>开始编写 &lt;code>Array&amp;lt;T, S&amp;gt;&lt;/code>。&lt;/li>
&lt;li>&lt;mark>重点&lt;/mark>：这里的 &lt;code>T&lt;/code> 是元素类型，&lt;code>S&lt;/code> 是&lt;mark>编译期常量&lt;/mark>（数组大小）。作者解释了为什么在 C++ 中&lt;mark>通过模板传递数组大小比通过构造函数传递更高效（因为它在编译时就确定了内存空间）&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>内存分配的核心：原始数组&lt;/mark>
&lt;ul>
&lt;li>在类内部定义 &lt;code>T m_Data[S]&lt;/code>。&lt;/li>
&lt;li>&lt;mark>关键点&lt;/mark>：这证明了 &lt;code>Array&lt;/code> 是分配在&lt;mark>栈&lt;/mark>上的，其生命周期由作用域决定。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>实现 &lt;code>Size()&lt;/code> 方法&lt;/mark>
&lt;ul>
&lt;li>定义一个简单的 &lt;code>constexpr size_t Size() const { return S; }&lt;/code>。&lt;/li>
&lt;li>强调了 &lt;code>constexpr&lt;/code> 的作用，让这个大小在编译阶段就能被其他代码使用。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>运算符重载：实现 &lt;code>operator[]&lt;/code>&lt;/mark>
&lt;ul>
&lt;li>为了像使用普通数组一样使用它（例如 &lt;code>data[0]&lt;/code>），作者演示了如何编写两个版本的下标运算符：
&lt;ol>
&lt;li>&lt;mark>普通版本&lt;/mark>：&lt;code>T&amp;amp; operator[](size_t index)&lt;/code>。&lt;/li>
&lt;li>&lt;mark>Const 版本&lt;/mark>：&lt;code>const T&amp;amp; operator[](size_t index) const&lt;/code>（为了处理 &lt;code>const Array&lt;/code> 对象）。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>内存布局验证&lt;/mark>
&lt;ul>
&lt;li>作者通过调试器（Debugger）展示了 &lt;code>Array&lt;/code> 在内存中的连续排布情况。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>总结与后续预告&lt;/mark>
&lt;ul>
&lt;li>这集完成了一个&lt;mark>静态的由栈分配的数组&lt;/mark> &lt;del>连续存储一定数量数据元素&lt;/del> 。作者提到，下一集（92 集）将在此基础上引入&lt;mark>堆（Heap）内存分配&lt;/mark>，实现动态扩容的 &lt;code>Vector&lt;/code>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>&lt;em>用C++编写一个固定大小，基于栈分配的数组数据结构&lt;/em>&lt;/p>
&lt;h1 id="91静态数组实现">91静态数组实现&lt;a class="anchor" href="#91%e9%9d%99%e6%80%81%e6%95%b0%e7%bb%84%e5%ae%9e%e7%8e%b0">#&lt;/a>&lt;/h1>
&lt;h2 id="栈分配和堆分配">栈分配和堆分配&lt;a class="anchor" href="#%e6%a0%88%e5%88%86%e9%85%8d%e5%92%8c%e5%a0%86%e5%88%86%e9%85%8d">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP91
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;array&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> k &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> const_k &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; &lt;span style="color:#75715e">//常量表达式，编译时可确定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//栈分配
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//int myarray[k];//编译出错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//const_k必须是编译时已知的常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> myarray[const_k];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> i&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>;i&lt;span style="color:#f92672">&amp;lt;&lt;/span>const_k;i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//未初始化，值为栈上的垃圾值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> myarray[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//myarray在栈帧弹出时自动释放
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//堆分配，且用指针寻址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//动态分配，大小无需在编译时确定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> heapArray &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[k];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span>[] heapArray; &lt;span style="color:#75715e">//释放堆内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//c++11提供的标准数组，大小必须在编译时确定
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//这是个模板类，通过模板指定类型和大小
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// _EXPORT_STD template &amp;lt;class _Ty, size_t _Size&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>array&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#ae81ff">5&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> collection;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	collection.size();&lt;span style="color:#75715e">//成员函数，返回数组大小
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> collection.size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> collection[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//要让 for (int i : collection) 运行，C++ 编译器会寻找两个特定的函数：begin() 和 end()。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i : collection)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="使用alloca函数在栈上分配内存">使用alloca函数在栈上分配内存&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8alloca%e5%87%bd%e6%95%b0%e5%9c%a8%e6%a0%88%e4%b8%8a%e5%88%86%e9%85%8d%e5%86%85%e5%ad%98">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP91
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Array&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Array(&lt;span style="color:#66d9ef">int&lt;/span> size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//alloca函数在栈上分配内存，分配的内存在当前函数返回时自动释放
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Data &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)alloca(size &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Array arr(size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="代码示例">代码示例&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP91
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//size_t 的使命是“能够表示内存中最大的对象”，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//在几位的机器上运行就是几位大小
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T, size_t S&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Array&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译期常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">constexpr&lt;/span> size_t Size() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> S;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这样会导致取出数组元素后会被复制，且也无法修改
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//T operator[] (int index)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//返回引用，是能修改的左值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//1. 普通版本：允许读写
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	T&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[] (size_t index)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//2：只允许读,而且返回const引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//通过这个返回的普通引用，别人依然可以修改 m_Data 里的内容，这违背了函数末尾 const 的初衷
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	 &lt;span style="color:#75715e">//T&amp;amp; operator[] (int index) const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//2：只允许读,而且返回const引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//取决于你调用该函数的对象本身是否是 const,是const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//对象则调用该重载版本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[] (size_t index) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">Data&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//常量版本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">Data&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T m_Data[S];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//每次创建新类，编译器都会根据模板参数生成一个新的类
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Array&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#ae81ff">5&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//每个字节都是 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	memset(&lt;span style="color:#f92672">&amp;amp;&lt;/span>data, &lt;span style="color:#ae81ff">1&lt;/span>, data.Size() &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//每个字节都是 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	memset(data.Data(), &lt;span style="color:#ae81ff">2&lt;/span>, data.Size() &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//把数组中每个字节设为0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	memset(&lt;span style="color:#f92672">&amp;amp;&lt;/span>data[&lt;span style="color:#ae81ff">0&lt;/span>], &lt;span style="color:#ae81ff">0&lt;/span>, data.Size() &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译期的断言检查。让编译器在把代码编译成程序之前，先检查一下你的逻辑对不对，如果条件不满足，编译器会直接报错并拒绝生成程序 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">static_assert&lt;/span>(data.Size() &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#e6db74">&amp;#34;Size is too large!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//因为data.Size()是编译期常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Array&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string, data.Size()&lt;span style="color:#f92672">&amp;gt;&lt;/span> a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> arrayReference &lt;span style="color:#f92672">=&lt;/span> data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//arrayReference[2] = 3; //
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//arrayReference是const修饰的，编译器只能调用带有 const 后缀的版本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> arrayReference[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> data.Size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//data[i] = i;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Array&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string, &lt;span style="color:#ae81ff">3&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> data1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data1[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data1[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;world&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> data1.Size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//data[i] = i;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data1[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">hello
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">world
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>93迭代器详解</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/93%E8%BF%AD%E4%BB%A3%E5%99%A8%E8%AF%A6%E8%A7%A3/</link><pubDate>Sun, 08 Mar 2026 19:58:54 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/93%E8%BF%AD%E4%BB%A3%E5%99%A8%E8%AF%A6%E8%A7%A3/</guid><description>&lt;ul>
&lt;li>&lt;mark>迭代器的基本定义&lt;/mark>迭代器是一个对象，其行为类似于指针，用于遍历容器中的元素。它提供了一种统一的方法来访问不同类型容器（如数组、链表、树）中的数据，而无需了解容器的底层实现。&lt;/li>
&lt;li>==为什么需要迭代器？==不同的容器有不同的存储结构（&lt;mark>内存连续或不连续&lt;/mark>）。迭代器将“遍历数据”这一行为抽象化，使得开发者可以使用相同的语法（如 &lt;code>++&lt;/code> 或 &lt;code>*&lt;/code>）来处理各种复杂的集合。&lt;/li>
&lt;li>&lt;mark>核心概念：begin() 与 end()&lt;/mark>
&lt;ul>
&lt;li>&lt;mark>&lt;code>begin()&lt;/code>&lt;/mark>：返回指向容器中第一个元素的迭代器。&lt;/li>
&lt;li>&lt;mark>&lt;code>end()&lt;/code>&lt;/mark>：返回指向容器中&lt;mark>最后一个元素之后&lt;/mark>位置的迭代器（即“越界”位置）。这用于标记遍历的结束。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>迭代器的基本操作&lt;/mark>演示了如何使用迭代器进行手动遍历：
&lt;ul>
&lt;li>使用 &lt;code>*it&lt;/code>（解引用）获取当前元素的值。&lt;/li>
&lt;li>使用 &lt;code>++it&lt;/code> 将迭代器移动到下一个元素。&lt;/li>
&lt;li>使用 &lt;code>it != map.end()&lt;/code> 作为循环终止条件。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>==现代 C++ 中的简化写法 (Range-based for loop)==解释了基于范围的 &lt;code>for&lt;/code> 循环（如 &lt;code>for (auto&amp;amp; v : values)&lt;/code>）在底层其实就是通过调用容器的 &lt;code>begin()&lt;/code> 和 &lt;code>end()&lt;/code> 迭代器来实现的。&lt;/li>
&lt;li>==在不同容器中的应用（以 std::map 为例）==演示了由于 &lt;code>std::map&lt;/code> 不是连续内存空间，不能使用下标 &lt;code>[i]&lt;/code> 遍历，此时迭代器是访问元素的唯一标准方式。对于 &lt;code>map&lt;/code>，迭代器指向的是 &lt;code>std::pair&lt;/code> 类型。&lt;/li>
&lt;/ul>
&lt;h1 id="简单例子">简单例子&lt;a class="anchor" href="#%e7%ae%80%e5%8d%95%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;p>std::vector有几种迭代器：&lt;/p>
&lt;p>&lt;img src="img/ly-20260308215913654.png" alt="" />&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP86
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//无序映射（哈希表）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;unordered_map&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> values &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span>,&lt;span style="color:#ae81ff">4&lt;/span>,&lt;span style="color:#ae81ff">5&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> values.size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//没有索引系统的集合类型，无法使用下标访问元素
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> values[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====0===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//基于范围的for循环
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> value : values)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====1===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//values.end()返回一个超出可接受范围的迭代器对象，是个无效迭代器，是最后一个元素的下一个元素，所以不能访问它指向的元素
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//当你修改容器（添加、删除或重新分配内存）时，指向该容器元素的迭代器可能会变得像“野指针”一样，指向错误的内存地址。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;::&lt;/span>iterator it &lt;span style="color:#f92672">=&lt;/span> values.begin(); it &lt;span style="color:#f92672">!=&lt;/span> values.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//像对待指针那样，进行解引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//因为实际的迭代器类里实现了类似星号的解引用操作符重载 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>it &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====2===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">using&lt;/span> ScoreMap &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>unordered_map&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string, &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ScoreMap map;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">using&lt;/span> ScoreMapConstIter &lt;span style="color:#f92672">=&lt;/span> ScoreMap&lt;span style="color:#f92672">::&lt;/span>const_iterator;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	map[&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	map[&lt;span style="color:#e6db74">&amp;#34;c++&amp;#34;&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不修改容器中的元素时，使用const_iterator
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (ScoreMapConstIter it &lt;span style="color:#f92672">=&lt;/span> map.begin(); it &lt;span style="color:#f92672">!=&lt;/span> map.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//*it是一个pair对象，first成员是key，second成员是value
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//auto&amp;amp;，引用，不会实际复制值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//迭代器指向的是 std::pair 类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> key &lt;span style="color:#f92672">=&lt;/span> it&lt;span style="color:#f92672">-&amp;gt;&lt;/span>first;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> it&lt;span style="color:#f92672">-&amp;gt;&lt;/span>second;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> key &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====3===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//kv的类型: std::pair&amp;lt;const std:;string,int&amp;gt; &amp;amp;kv
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> kv : map)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> key &lt;span style="color:#f92672">=&lt;/span> kv.first;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> kv.second;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> key &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;====4===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//c++17才支持
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//C++17 的结构化绑定 (Structured Bindings)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> [key,value] &lt;span style="color:#f92672">:&lt;/span> map)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> key &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====0===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====1===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====2===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno 5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">c++ 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====3===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno 5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">c++ 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====4===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno 5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">c++ 2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>86类型转换运算符</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/86%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E8%BF%90%E7%AE%97%E7%AC%A6/</link><pubDate>Sun, 08 Mar 2026 00:20:54 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/86%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2%E8%BF%90%E7%AE%97%E7%AC%A6/</guid><description>&lt;h1 id="核心概念">核心概念&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5">#&lt;/a>&lt;/h1>
&lt;p>这一集主要讲解了如何定义用户自定义类型转换运算符（User-Defined Conversion Operators），允许你将一个类或结构体的对象隐式或显式地转换为另一种类型（如 &lt;code>int&lt;/code>、&lt;code>float&lt;/code> 或其他自定义类）。&lt;/p>
&lt;h1 id="什么是转换运算符">什么是转换运算符&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e8%bd%ac%e6%8d%a2%e8%bf%90%e7%ae%97%e7%ac%a6">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>背景：通常我们使用构造函数来进行类型转换（例如 &lt;code>Entity(int x)&lt;/code> 可以将 &lt;code>int&lt;/code> 转为 &lt;code>Entity&lt;/code>）。而转换运算符则是反过来的：它定义了如何将你的对象转换为其他类型。&lt;/li>
&lt;li>语法：&lt;code>operator type() const { ... }&lt;/code>。注意它没有返回类型，因为返回类型已经包含在函数名中了。&lt;/li>
&lt;/ul>
&lt;h1 id="代码示例">代码示例&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>假设有一个 &lt;code>Entity&lt;/code> 类，包含 &lt;code>std::string Name&lt;/code> 和 &lt;code>int Age&lt;/code>。&lt;/li>
&lt;li>如果你希望将 &lt;code>Entity&lt;/code> 对象直接赋值给一个 &lt;code>int&lt;/code>（代表 Age），可以写：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">int&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> Age; }&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>这样在调用 &lt;code>int a = entity;&lt;/code> 时，编译器会自动调用该运算符。&lt;/li>
&lt;/ul>
&lt;h2 id="简单代码">简单代码&lt;a class="anchor" href="#%e7%ae%80%e5%8d%95%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP86
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Orange&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">float&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">3.14f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintFloat&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;PrintFloat(): &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Orange orange;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> f &lt;span style="color:#f92672">=&lt;/span> orange; &lt;span style="color:#75715e">//隐式转换，调用 operator float()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> f &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; &lt;span style="color:#75715e">// 输出 3.14
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> (&lt;span style="color:#66d9ef">float&lt;/span>)orange &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; &lt;span style="color:#75715e">// 输出 3.14
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	PrintFloat(f);&lt;span style="color:#75715e">//orange先隐式转换成float
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="例子作用域指针-bool转换符">(例子)作用域指针-bool转换符&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90%e4%bd%9c%e7%94%a8%e5%9f%9f%e6%8c%87%e9%92%88-bool%e8%bd%ac%e6%8d%a2%e7%ac%a6">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP86
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ScopedPtr&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ScopedPtr() &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ScopedPtr(T&lt;span style="color:#f92672">*&lt;/span> ptr) &lt;span style="color:#f92672">:&lt;/span> m_Ptr(ptr) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>ScopedPtr() { &lt;span style="color:#66d9ef">delete&lt;/span> m_Ptr; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//指针是否有效
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#a6e22e">IsValid&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Ptr &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//把对象实例转为bool类型，判断指针是否有效
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">/*explicit*/&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">bool&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> IsValid(); }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">Get&lt;/span>() { &lt;span style="color:#66d9ef">return&lt;/span> m_Ptr; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> T&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">Get&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Ptr; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	T&lt;span style="color:#f92672">*&lt;/span> m_Ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> X &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>, Y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">ProcessEntity&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> ScopedPtr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&amp;amp;&lt;/span> entity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (entity) &lt;span style="color:#75715e">//隐式调用 operator bool()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity position: (&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> (&lt;span style="color:#f92672">*&lt;/span>(entity.Get())).X &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> (&lt;span style="color:#f92672">*&lt;/span>(entity.Get())).Y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Invalid entity pointer.&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式调用ScopedPtr(T* ptr)构造函数创建ScopedPtr对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ScopedPtr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> e &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Entity();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ProcessEntity(e); &lt;span style="color:#75715e">//输出 Entity position: (0, 0)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/* std::unique_ptr源码 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	 explicit operator bool() const noexcept {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> return get() != nullptr;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> }
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> e(&lt;span style="color:#66d9ef">new&lt;/span> Entity());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//因为独占指针也可以转换为bool类型 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ProcessEntity(e);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="例子定时器">(例子)定时器&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90%e5%ae%9a%e6%97%b6%e5%99%a8">#&lt;/a>&lt;/h2>
&lt;p>直接转成双精度（总定时时间）&lt;/p></description></item><item><title>90stdmove与移动运算符</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/90stdmove%E4%B8%8E%E7%A7%BB%E5%8A%A8%E8%BF%90%E7%AE%97%E7%AC%A6/</link><pubDate>Sat, 07 Mar 2026 16:53:59 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/90stdmove%E4%B8%8E%E7%A7%BB%E5%8A%A8%E8%BF%90%E7%AE%97%E7%AC%A6/</guid><description>&lt;h1 id="stdmove-到底是什么">&lt;code>std::move&lt;/code> 到底是什么？&lt;a class="anchor" href="#stdmove-%e5%88%b0%e5%ba%95%e6%98%af%e4%bb%80%e4%b9%88">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>核心真相&lt;/mark>：&lt;code>std::move&lt;/code> &lt;mark>并不移动任何东西&lt;/mark>。它只是一个简单的类型转换（Casting）。&lt;/li>
&lt;li>&lt;mark>底层逻辑&lt;/mark>：它把一个左值（Lvalue）强制转换为右值引用（Rvalue Reference）。它的作用仅仅是告诉编译器：“嘿，&lt;mark>我知道这个变量原本是个持久的对象，但现在我不再需要它了，请把它当成一个临时对象，允许别人‘偷’走它的资源&lt;/mark>。”&lt;/li>
&lt;li>&lt;mark>代码本质&lt;/mark>：&lt;code>std::move(x)&lt;/code> 基本上等同于 &lt;code>static_cast&amp;lt;T&amp;amp;&amp;amp;&amp;gt;(x)&lt;/code>。&lt;/li>
&lt;/ul>
&lt;h1 id="移动赋值运算符-move-assignment-operator">移动赋值运算符 (Move Assignment Operator)&lt;a class="anchor" href="#%e7%a7%bb%e5%8a%a8%e8%b5%8b%e5%80%bc%e8%bf%90%e7%ae%97%e7%ac%a6-move-assignment-operator">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>场景引入&lt;/mark>：第 89 集讲的是构造新对象，而这一集讲的是&lt;mark>给已有对象重新赋值&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>String dest &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//如果你只写了移动构造，没写移动赋值：编译器会“退而求其
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//次”，去调用拷贝赋值运算符 operator=(const String&amp;amp; other)。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>dest &lt;span style="color:#f92672">=&lt;/span> String(&lt;span style="color:#e6db74">&amp;#34;World&amp;#34;&lt;/span>); &lt;span style="color:#75715e">// 这里会涉及移动赋值
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>
&lt;p>&lt;mark>手写实现步骤&lt;/mark>：&lt;/p>
&lt;ol>
&lt;li>&lt;mark>清理旧资源&lt;/mark>：在接管别人的资源前，必须先 &lt;code>delete[] m_Data&lt;/code> 释放自己当前的内存（否则会内存泄漏）。&lt;/li>
&lt;li>&lt;mark>接管资源&lt;/mark>：像移动构造函数一样，把对方的指针和大小拷过来。&lt;/li>
&lt;li>&lt;mark>置空对方&lt;/mark>：将源对象的指针设为 &lt;code>nullptr&lt;/code>。&lt;/li>
&lt;li>&lt;mark>返回自身&lt;/mark>：&lt;code>return *this;&lt;/code> 以支持链式赋值。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h1 id="为什么-stdmove-是必需的">为什么 &lt;code>std::move&lt;/code> 是必需的？&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88-stdmove-%e6%98%af%e5%bf%85%e9%9c%80%e7%9a%84">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>实战演示&lt;/mark>：Cherno 展示了当你想&lt;mark>把一个已命名的变量移动到另一个地方&lt;/mark>时，必须显式使用 &lt;code>std::move&lt;/code>。&lt;/li>
&lt;li>&lt;mark>原因&lt;/mark>：即使一个变量的类型是 &lt;code>String&amp;amp;&amp;amp;&lt;/code>，只要它有名字，它就是一个&lt;mark>左值&lt;/mark>。&lt;/li>
&lt;li>&lt;mark>安全性&lt;/mark>：这种设计是为了防止你无意中移动了以后还要用到的数据。使用 &lt;code>std::move&lt;/code> 是一种显式的“主权放弃”。&lt;/li>
&lt;/ul>
&lt;h1 id="常见的错误用法与陷阱">常见的错误用法与陷阱&lt;a class="anchor" href="#%e5%b8%b8%e8%a7%81%e7%9a%84%e9%94%99%e8%af%af%e7%94%a8%e6%b3%95%e4%b8%8e%e9%99%b7%e9%98%b1">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>不要移动 &lt;code>const&lt;/code> 对象&lt;/mark>：如果你尝试 &lt;code>std::move&lt;/code> 一个 &lt;code>const&lt;/code> 对象，它会默默地退化回&lt;mark>拷贝&lt;/mark>。因为移动语义需要修改原对象（将其置空），而 &lt;code>const&lt;/code> 禁止修改。&lt;/li>
&lt;li>&lt;mark>自赋值检查&lt;/mark>：在移动赋值运算符中，通常建议检查 &lt;code>if (this != &amp;amp;other)&lt;/code>，防止自己移动给自己导致资源被意外提前释放。&lt;/li>
&lt;/ul>
&lt;h1 id="例子1移动构造函数与移动赋值函数">(例子1)移动构造函数与移动赋值函数&lt;a class="anchor" href="#%e4%be%8b%e5%ad%901%e7%a7%bb%e5%8a%a8%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0%e4%b8%8e%e7%a7%bb%e5%8a%a8%e8%b5%8b%e5%80%bc%e5%87%bd%e6%95%b0">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//c++11才引入了右值引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;utility&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">// std::move 在这个头文件里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">String&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String() &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Created!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		memcpy(m_Data, string, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const char* string)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copied!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在 C++ 中，访问控制（public/private）是基于“类（Class）”层面的，而不是基于“对象（Object）”层面的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//简单来说：只要是在 String 类的成员函数内部，你就可以访问任何 String 对象的私有成员。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const String&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//移动构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//接收一个右值引用参数，表示可以从一个将要被销毁的临时对象中“窃取”资源，而不是复制资源。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果手动定义了“移动构造函数”，编译器就不再为你自动生成“默认赋值运算符”了。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Moved!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;&lt;span style="color:#75715e">//将原对象的大小置为0，表示它不再拥有资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//把被接管控制权的资源指针置空，防止原对象的析构函数删除已经被移动的资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(String&amp;amp;&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>String()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Destroyed!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;~String()&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 移动赋值运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Move Assigned!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 1. 自赋值检查 (防止自己移动给自己，如 a = std::move(a))
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 2. 释放旧资源 (dest 已经有内存了，必须先删掉，否则内存泄漏)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 3. 窃取资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 4. 将原对象置空 (让它变成空壳)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//拷贝赋值运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copy Assigned!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size]; &lt;span style="color:#75715e">// 必须申请新内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">uint32_t&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			printf(&lt;span style="color:#e6db74">&amp;#34;%c&amp;#34;&lt;/span>, m_Data[i]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个通过 typedef 或 using 定义的类型，表示
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//无符号整型32位数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// int 在某些古老的 16 位系统上可能是 2 字节，在现代系统上通常是 4 字节，uint32_t 强制规定在任何符合标准的编译器上，它永远是 32 位（4 字节）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity(const String&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Entity(String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//一旦右值引用有了名字，它在后续表达式中就变成了左值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//编译器会想：“这个 name 虽然是引用进来的，但它现在是有名有姓的变量，为了安全起见，我必须调用 复制构造函数 来保护它。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	:m_Name(name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	std::cout &amp;lt;&amp;lt; &amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//接收一个临时对象作为参数，使用移动语义来构造 Entity 对象，避免不必要的复制，提高性能。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//强转为右值引用，告诉编译器：我知道 name 是一个左值，但我想把它当作一个将要被销毁的临时对象来处理，所以请调用 移动构造函数 来构造 m_Name。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//:m_Name((String&amp;amp;&amp;amp;)name) //这种写法也行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(std&lt;span style="color:#f92672">::&lt;/span>move(name)) &lt;span style="color:#75715e">// 将左值 name 强行转回右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里将&amp;#34;Cherno&amp;#34;隐式调用构造函数构造了一个String
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//之后move给了Entity（Entity内部的m_Name接管了这个临时String指针指向的堆内存）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	entity.PrintName();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;===0==&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;===1==&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String dest &lt;span style="color:#f92672">=&lt;/span> string;&lt;span style="color:#75715e">//这是复制
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;===2==&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String dest1 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(string);&lt;span style="color:#75715e">//调用移动构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	dest1.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;===3==&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果没写移动赋值,编译器会“退而求其次”，去调用拷贝赋值运算符 operator=(const String &amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	dest &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;abc&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;===4==&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	dest &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	dest.Print();&lt;span style="color:#75715e">//string已经被移动了，变成了空壳，所以dest打印出来是空的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity( String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">===0==
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">===1==
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Copied!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const String&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">===2==
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Hello
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">===3==
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Move Assigned!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">===4==
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Move Assigned!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="例子2详细解释">(例子2)详细解释&lt;a class="anchor" href="#%e4%be%8b%e5%ad%902%e8%af%a6%e7%bb%86%e8%a7%a3%e9%87%8a">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//c++11才引入了右值引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;utility&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">// std::move 在这个头文件里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">String&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String() &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Created!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		memcpy(m_Data, string, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const char* string)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copied!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在 C++ 中，访问控制（public/private）是基于“类（Class）”层面的，而不是基于“对象（Object）”层面的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//简单来说：只要是在 String 类的成员函数内部，你就可以访问任何 String 对象的私有成员。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const String&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//移动构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//接收一个右值引用参数，表示可以从一个将要被销毁的临时对象中“窃取”资源，而不是复制资源。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果手动定义了“移动构造函数”，编译器就不再为你自动生成“默认赋值运算符”了。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Moved!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;&lt;span style="color:#75715e">//将原对象的大小置为0，表示它不再拥有资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//把被接管控制权的资源指针置空，防止原对象的析构函数删除已经被移动的资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(String&amp;amp;&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>String()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Destroyed!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;~String()&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 移动赋值运算符：将另一个对象，移入当前这个对象自身
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//语义契约（Semantic Contract）。	C++ 的设计哲学是：让自定义类型的行为表现得像内置类型（如 int）一样。标准做法始终是返回非 const 的 *this 引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Move Assigned!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 1. 自赋值检查 (防止自己移动给自己，如 a = std::move(a)，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 因为如下是会释放旧资源的，所以移动给自己就什么都没有了)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 2. 释放旧资源 (dest[当前对象] 已经有内存了，必须先删掉，否则内存泄漏)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 3. 窃取资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 4. 将原对象置空 (让它变成空壳)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//找到 this 指向的对象，返回它的引用（别名），
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 而不是创建一个新的副本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//拷贝赋值运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copy Assigned!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size]; &lt;span style="color:#75715e">// 必须申请新内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">uint32_t&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			printf(&lt;span style="color:#e6db74">&amp;#34;%c&amp;#34;&lt;/span>, m_Data[i]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个通过 typedef 或 using 定义的类型，表示
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//无符号整型32位数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// int 在某些古老的 16 位系统上可能是 2 字节，在现代系统上通常是 4 字节，uint32_t 强制规定在任何符合标准的编译器上，它永远是 32 位（4 字节）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity(const String&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Entity(String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//一旦右值引用有了名字，它在后续表达式中就变成了左值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//编译器会想：“这个 name 虽然是引用进来的，但它现在是有名有姓的变量，为了安全起见，我必须调用 复制构造函数 来保护它。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	:m_Name(name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	std::cout &amp;lt;&amp;lt; &amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//接收一个临时对象作为参数，使用移动语义来构造 Entity 对象，避免不必要的复制，提高性能。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//强转为右值引用，告诉编译器：我知道 name 是一个左值，但我想把它当作一个将要被销毁的临时对象来处理，所以请调用 移动构造函数 来构造 m_Name。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//:m_Name((String&amp;amp;&amp;amp;)name) //这种写法也行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(std&lt;span style="color:#f92672">::&lt;/span>move(name)) &lt;span style="color:#75715e">// 将左值 name 强行转回右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//临时对象经历了:Created! -&amp;gt; Moved! -&amp;gt; Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//打印字符串
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	entity.PrintName();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====0=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式调用构造函数String(const char* string)，Created! 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====1=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式调用(复制)构造函数， 本质上就是“通过复制一个已有的对象来创建一个新对象”，这就是所谓的“复制构造”。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String dest &lt;span style="color:#f92672">=&lt;/span> string;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====2.1=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//使用接受字符串右值引用的构造函数，来构造一个String
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String dest1 &lt;span style="color:#f92672">=&lt;/span> (String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>)string;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====2.2=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String dest2((String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span>)string);&lt;span style="color:#75715e">//这个string内部的指针已经被dest1接管了，所以dest2构造的时候，string已经是空壳了，所以dest2也是空的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====2.3=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这样写无需知道string是什么类型的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//remove_reference_t&amp;lt;_Ty&amp;gt;&amp;amp;&amp;amp; move(_Ty&amp;amp;&amp;amp; _Arg) ，查看源码可知返回的是右值引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//这里是移动构造，而非移动赋值，因为dest3是第一次定义并使用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String dest3 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====3=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//当将一个变量(数值、表达式)赋给一个已有变量时，使用的是赋值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//就像这里是移动赋值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	dest &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity( String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====0=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====1=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Copied!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const String&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====2.1=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====2.2=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====2.3=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====3=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Move Assigned!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="例子3视频举的">(例子3)视频举的&lt;a class="anchor" href="#%e4%be%8b%e5%ad%903%e8%a7%86%e9%a2%91%e4%b8%be%e7%9a%84">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//c++11才引入了右值引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;utility&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">// std::move 在这个头文件里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">String&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String() &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Created!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		memcpy(m_Data, string, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const char* string)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copied!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在 C++ 中，访问控制（public/private）是基于“类（Class）”层面的，而不是基于“对象（Object）”层面的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//简单来说：只要是在 String 类的成员函数内部，你就可以访问任何 String 对象的私有成员。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const String&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//移动构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//接收一个右值引用参数，表示可以从一个将要被销毁的临时对象中“窃取”资源，而不是复制资源。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果手动定义了“移动构造函数”，编译器就不再为你自动生成“默认赋值运算符”了。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Moved!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;&lt;span style="color:#75715e">//将原对象的大小置为0，表示它不再拥有资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//把被接管控制权的资源指针置空，防止原对象的析构函数删除已经被移动的资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(String&amp;amp;&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>String()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Destroyed!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;~String()&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 移动赋值运算符：将另一个对象，移入当前这个对象自身
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//语义契约（Semantic Contract）。	C++ 的设计哲学是：让自定义类型的行为表现得像内置类型（如 int）一样。标准做法始终是返回非 const 的 *this 引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Move Assigned!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 1. 自赋值检查 (防止自己移动给自己，如 a = std::move(a)，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 因为如下是会释放旧资源的，所以移动给自己就什么都没有了)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 2. 释放旧资源 (dest[当前对象] 已经有内存了，必须先删掉，否则内存泄漏)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 3. 窃取资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">// 4. 将原对象置空 (让它变成空壳)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//找到 this 指向的对象，返回它的引用（别名），
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 而不是创建一个新的副本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//拷贝赋值运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copy Assigned!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size]; &lt;span style="color:#75715e">// 必须申请新内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">uint32_t&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			printf(&lt;span style="color:#e6db74">&amp;#34;%c&amp;#34;&lt;/span>, m_Data[i]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个通过 typedef 或 using 定义的类型，表示
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//无符号整型32位数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// int 在某些古老的 16 位系统上可能是 2 字节，在现代系统上通常是 4 字节，uint32_t 强制规定在任何符合标准的编译器上，它永远是 32 位（4 字节）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity(const String&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Entity(String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//一旦右值引用有了名字，它在后续表达式中就变成了左值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//编译器会想：“这个 name 虽然是引用进来的，但它现在是有名有姓的变量，为了安全起见，我必须调用 复制构造函数 来保护它。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	:m_Name(name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	std::cout &amp;lt;&amp;lt; &amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//接收一个临时对象作为参数，使用移动语义来构造 Entity 对象，避免不必要的复制，提高性能。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//强转为右值引用，告诉编译器：我知道 name 是一个左值，但我想把它当作一个将要被销毁的临时对象来处理，所以请调用 移动构造函数 来构造 m_Name。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//:m_Name((String&amp;amp;&amp;amp;)name) //这种写法也行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(std&lt;span style="color:#f92672">::&lt;/span>move(name)) &lt;span style="color:#75715e">// 将左值 name 强行转回右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====0=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//使用String(const char* string)构造String对象，Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		String apple &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Apple&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//使用默认构造函数构造String对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		String dest;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====1=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Apple: &amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		apple.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Dest: &amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		dest.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====1=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//使用移动赋值运算符将apple的资源移入dest，Move Assigned!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//相当于dest.operator=(std::move(apple));
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		dest &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(apple);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====2=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Apple: &amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		apple.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Dest: &amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		dest.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=====2=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//综上，没有任何复制就移动了整个字符数组的所有权，交换了两个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/* 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====0=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====1=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Apple: Apple
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Dest:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====1=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Move Assigned!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====2=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Apple:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Dest: Apple
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=====2=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="结尾--总结拷贝-vs-移动">结尾 | 总结：拷贝 vs 移动&lt;a class="anchor" href="#%e7%bb%93%e5%b0%be--%e6%80%bb%e7%bb%93%e6%8b%b7%e8%b4%9d-vs-%e7%a7%bb%e5%8a%a8">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>拷贝 (Copy)&lt;/mark>：两份独立的资源，安全但慢。&lt;/li>
&lt;li>&lt;mark>移动 (Move)&lt;/mark>：一份资源的所有权转移，极快。&lt;/li>
&lt;li>&lt;mark>金句&lt;/mark>：如果你希望你的 C++ 程序拥有极致性能，学会何时及如何使用 &lt;code>std::move&lt;/code> 是必修课。&lt;/li>
&lt;li>当包含移动构造函数时，应该也包含移动赋值函数&lt;/li>
&lt;/ul></description></item><item><title>89移动语义</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/89%E7%A7%BB%E5%8A%A8%E8%AF%AD%E4%B9%89/</link><pubDate>Sat, 07 Mar 2026 12:53:20 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/89%E7%A7%BB%E5%8A%A8%E8%AF%AD%E4%B9%89/</guid><description>&lt;h1 id="为什么要引入移动语义">为什么要引入移动语义？&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e8%a6%81%e5%bc%95%e5%85%a5%e7%a7%bb%e5%8a%a8%e8%af%ad%e4%b9%89">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>核心痛点&lt;/mark>：在 C++11 之前，将对象从一处转移到另一处通常只能通过“拷贝”。&lt;/p>
&lt;ul>
&lt;li>向一个函数传递一个对象&lt;/li>
&lt;li>从函数返回一个对象
&lt;ul>
&lt;li>如果有返回值优化&lt;mark>RVO (Return Value Optimization)&lt;/mark>。&lt;mark>编译器直接在调用者（Caller）的栈帧中构造该对象&lt;/mark>，而不是在函数内部构造再拷贝出来。结果：既没有拷贝构造，也没有移动构造，性能损耗为零。&lt;/li>
&lt;li>当编译器因为逻辑复杂（例如根据条件返回不同的局部变量）而无法进行 RVO 时，移动语义就成了“二号救兵”。
&lt;ul>
&lt;li>旧时代 (C++11 之前)：&lt;mark>如果 RVO 失效，必须调用拷贝构造函数&lt;/mark>，这涉及昂贵的深拷贝。&lt;/li>
&lt;li>现代 C++ (C++11 之后)：编译器会&lt;mark>尝试调用移动构造函数&lt;/mark>。1. 因为返回的对象是一个即将销毁的右值，它可以被“掠夺”。2. 你不需要手动写 return std::move(obj);，编译器会&lt;mark>自动处理局部变量的返回&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>性能代价&lt;/mark>：如果对象持有堆内存（如字符串或数组），拷贝意味着：&lt;mark>申请新内存 -&amp;gt; 复制所有数据 -&amp;gt; 销毁旧对象&lt;/mark>。这在处理临时对象（扔掉的对象）时是非常巨大的浪费。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>解决方案&lt;/mark>：如果我们可以直接“移动”对象——即把旧对象的内存指针直接交给新对象，就能省去内存分配和数据复制的开销。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;h1 id="基础构建实验用的-string-类">基础：构建实验用的 &lt;code>String&lt;/code> 类&lt;a class="anchor" href="#%e5%9f%ba%e7%a1%80%e6%9e%84%e5%bb%ba%e5%ae%9e%e9%aa%8c%e7%94%a8%e7%9a%84-string-%e7%b1%bb">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>模拟场景&lt;/mark>：Cherno 编写了一个简易的 &lt;code>String&lt;/code> 类，包含一个 &lt;code>char*&lt;/code> 指针和 &lt;code>size&lt;/code>。&lt;/li>
&lt;li>&lt;mark>可视化调试&lt;/mark>：在构造函数中加入 &lt;code>printf(&amp;quot;Created&amp;quot;)&lt;/code>，在拷贝构造函数中加入 &lt;code>printf(&amp;quot;Copied&amp;quot;)&lt;/code>，以便观察内存分配发生的时机。&lt;/li>
&lt;/ul>
&lt;h1 id="拷贝的代价演示">拷贝的代价演示&lt;a class="anchor" href="#%e6%8b%b7%e8%b4%9d%e7%9a%84%e4%bb%a3%e4%bb%b7%e6%bc%94%e7%a4%ba">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>实验代码&lt;/mark>：创建一个 &lt;code>Entity&lt;/code> 类，它拥有一个 &lt;code>String&lt;/code> 成员。当通过构造函数传入一个字符串字面量时，会发现控制台打印了 &lt;mark>“Created”&lt;/mark> 然后是 &lt;mark>“Copied”&lt;/mark>。&lt;/li>
&lt;li>&lt;mark>问题分析&lt;/mark>：即便传入的是一个临时字符串（右值），&lt;code>Entity&lt;/code> 仍然会调用拷贝构造函数进行深拷贝。明明临时对象马上就要销毁了，我们却还要复制它，这很不科学。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP89
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//c++11才引入了右值引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">String&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String() &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Created!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		memcpy(m_Data, string, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const char* string)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copied!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在 C++ 中，访问控制（public/private）是基于“类（Class）”层面的，而不是基于“对象（Object）”层面的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//简单来说：只要是在 String 类的成员函数内部，你就可以访问任何 String 对象的私有成员。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const String&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>String()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Destroyed!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;~String()&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">uint32_t&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			printf(&lt;span style="color:#e6db74">&amp;#34;%c&amp;#34;&lt;/span>, m_Data[i]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个通过 typedef 或 using 定义的类型，表示
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//无符号整型32位数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// int 在某些古老的 16 位系统上可能是 2 字节，在现代系统上通常是 4 字节，uint32_t 强制规定在任何符合标准的编译器上，它永远是 32 位（4 字节）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity(const String&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式构造函数构造String对象，调用String(const char* string)构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Entity entity(&amp;#34;Cherno&amp;#34;);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//临时对象String(&amp;#34;Cherno&amp;#34;)的生命周期直到支持它的那个“完整表达式”计算完成为止，即该行代码分号结束时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//!!现在main函数创建这个(临时)对象后，传(复制)给Entity构造函数的当参数使用，又马上销毁了这个临时对象(只留下复制的)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity(String(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	entity.PrintName();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Copied!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const String&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity(const String&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="编写移动构造函数-move-constructor">编写移动构造函数 (Move Constructor)&lt;a class="anchor" href="#%e7%bc%96%e5%86%99%e7%a7%bb%e5%8a%a8%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0-move-constructor">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>核心语法&lt;/mark>：使用右值引用 &lt;code>String(String&amp;amp;&amp;amp; other)&lt;/code>。注意要加上 &lt;code>noexcept&lt;/code> 关键字。&lt;/li>
&lt;li>&lt;mark>实现逻辑（偷走资源）&lt;/mark>：
&lt;ol>
&lt;li>直接将 &lt;code>this-&amp;gt;m_Data&lt;/code> 指向 &lt;code>other.m_Data&lt;/code>（浅拷贝指针）。&lt;/li>
&lt;li>将 &lt;code>this-&amp;gt;m_Size&lt;/code> 设为 &lt;code>other.m_Size&lt;/code>。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;li>&lt;mark>关键的一步（置空原对象）&lt;/mark>：必须将 &lt;code>other.m_Data&lt;/code> 设为 &lt;code>nullptr&lt;/code>，并将 &lt;code>other.m_Size&lt;/code> 设为 &lt;code>0&lt;/code>。&lt;/li>
&lt;li>&lt;mark>原理&lt;/mark>：这把旧对象变成了一个“空壳”。当旧对象析构时，&lt;code>delete nullptr&lt;/code> 不会做任何事，从而保证了内存所有权的完美转移。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP89
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//c++11才引入了右值引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;utility&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">// std::move 在这个头文件里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">String&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String() &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">default&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Created!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		memcpy(m_Data, string, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const char* string)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//复制构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Copied!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在 C++ 中，访问控制（public/private）是基于“类（Class）”层面的，而不是基于“对象（Object）”层面的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//简单来说：只要是在 String 类的成员函数内部，你就可以访问任何 String 对象的私有成员。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		memcpy(m_Data, other.m_Data, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(const String&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//移动构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//接收一个右值引用参数，表示可以从一个将要被销毁的临时对象中“窃取”资源，而不是复制资源。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">noexcept&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Moved!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不包括\0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Data &lt;span style="color:#f92672">=&lt;/span> other.m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		other.m_Size &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;&lt;span style="color:#75715e">//将原对象的大小置为0，表示它不再拥有资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//把被接管控制权的资源指针置空，防止原对象的析构函数删除已经被移动的资源
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		other.m_Data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;String(String&amp;amp;&amp;amp; other)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>String()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;Destroyed!&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;~String()&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">uint32_t&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> m_Size; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			printf(&lt;span style="color:#e6db74">&amp;#34;%c&amp;#34;&lt;/span>, m_Data[i]);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		printf(&lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个通过 typedef 或 using 定义的类型，表示
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//无符号整型32位数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// int 在某些古老的 16 位系统上可能是 2 字节，在现代系统上通常是 4 字节，uint32_t 强制规定在任何符合标准的编译器上，它永远是 32 位（4 字节）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name) 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity(const String&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Entity(String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//一旦右值引用有了名字，它在后续表达式中就变成了左值。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//编译器会想：“这个 name 虽然是引用进来的，但它现在是有名有姓的变量，为了安全起见，我必须调用 复制构造函数 来保护它。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	:m_Name(name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	std::cout &amp;lt;&amp;lt; &amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//接收一个临时对象作为参数，使用移动语义来构造 Entity 对象，避免不必要的复制，提高性能。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity(String&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//强转为右值引用，告诉编译器：我知道 name 是一个左值，但我想把它当作一个将要被销毁的临时对象来处理，所以请调用 移动构造函数 来构造 m_Name。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//:m_Name((String&amp;amp;&amp;amp;)name) //这种写法也行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(std&lt;span style="color:#f92672">::&lt;/span>move(name)) &lt;span style="color:#75715e">// 将左值 name 强行转回右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Entity( String&amp;amp;&amp;amp; name)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式构造函数构造String对象，调用String(const char* string)构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Entity entity(&amp;#34;Cherno&amp;#34;);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//临时对象String(&amp;#34;Cherno&amp;#34;)的生命周期直到支持它的那个“完整表达式”计算完成为止，即该行代码分号结束时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//!!现在main函数创建这个(临时)对象后，传(复制)给Entity构造函数的当参数使用，又马上销毁了这个临时对象(只留下复制的)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity(String(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	entity.PrintName();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(const char* string)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Moved!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">String(String&amp;amp;&amp;amp; other)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Entity( String&amp;amp;&amp;amp; name)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">~String()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="激活移动语义stdmove">激活移动语义：&lt;code>std::move&lt;/code>&lt;a class="anchor" href="#%e6%bf%80%e6%b4%bb%e7%a7%bb%e5%8a%a8%e8%af%ad%e4%b9%89stdmove">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>常见误区&lt;/mark>：即便写了移动构造函数，编译器在==某些情况下（如成员变量赋值）==可能仍会选择拷贝。&lt;/li>
&lt;li>&lt;mark>解决方法&lt;/mark>：在 &lt;code>Entity&lt;/code> 的构造函数中使用 &lt;code>m_Name(std::move(name))&lt;/code>。&lt;/li>
&lt;li>&lt;mark>效果验证&lt;/mark>：再次运行程序，你会发现 &lt;mark>“Copied”&lt;/mark> 变成了 &lt;mark>“Moved”&lt;/mark>。这意味着没有发生新的内存分配，程序运行得更快了。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP89_
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//#include &amp;lt;utility&amp;gt; //不加的话，std::move编译报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//int a=std::move(3);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="结尾--总结与展望">结尾 | 总结与展望&lt;a class="anchor" href="#%e7%bb%93%e5%b0%be--%e6%80%bb%e7%bb%93%e4%b8%8e%e5%b1%95%e6%9c%9b">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>核心价值&lt;/mark>：移动语义让你在不损失代码可读性的前提下，极大地提升了处理大型对象和临时对象的性能。&lt;/li>
&lt;/ul></description></item><item><title>85左值与右值</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/85%E5%B7%A6%E5%80%BC%E4%B8%8E%E5%8F%B3%E5%80%BC/</link><pubDate>Fri, 06 Mar 2026 22:42:42 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/85%E5%B7%A6%E5%80%BC%E4%B8%8E%E5%8F%B3%E5%80%BC/</guid><description>&lt;h1 id="什么是左值和右值">什么是左值和右值？&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e5%b7%a6%e5%80%bc%e5%92%8c%e5%8f%b3%e5%80%bc">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>核心定义&lt;/mark>：Cherno 用最简单的方式解释了两者。
&lt;ul>
&lt;li>&lt;mark>左值 (lvalue)&lt;/mark> &lt;del>定位值&lt;/del> ：有存储地址、有名字的变量。你可以给它赋值，它通常存在于表达式的左侧。&lt;/li>
&lt;li>&lt;mark>右值 (rvalue)&lt;/mark>：临时值，没有名字，通常在表达式结束后就销毁了（如字面量 &lt;code>10&lt;/code> 或临时函数返回值）。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>直观判定法&lt;/mark>：如果你能取这个东西的地址（使用 &lt;code>&amp;amp;&lt;/code> 运算符），它通常就是左值。&lt;/li>
&lt;/ul>
&lt;h1 id="左值引用-lvalue-references">左值引用 (lvalue references)&lt;a class="anchor" href="#%e5%b7%a6%e5%80%bc%e5%bc%95%e7%94%a8-lvalue-references">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>回顾&lt;/mark>：这就是我们常用的 &lt;code>int&amp;amp; a = b;&lt;/code>。&lt;/li>
&lt;li>&lt;mark>规则限制&lt;/mark>：左值引用&lt;mark>不能&lt;/mark>绑定到右值上。
&lt;ul>
&lt;li>&lt;code>int&amp;amp; a = 10;&lt;/code> 会报错，因为 &lt;code>10&lt;/code> 是右值。&lt;/li>
&lt;li>&lt;mark>例外情况&lt;/mark>：&lt;code>const int&amp;amp; a = 10;&lt;/code> 是合法的。编译器会产生一个临时变量来存放 &lt;code>10&lt;/code>，然后让引用绑定它。这在函数参数传递中非常常见。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h2 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP85
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">SetValueConst&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">SetValue1&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">SetValue&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetValue&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>;&lt;span style="color:#75715e">//10是一个右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetRefValue()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> i&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">10&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;GetRefValue():&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> i &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> i;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>;&lt;span style="color:#75715e">//i为左值，10为右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//10 = 3;//表达式必须为左值，10是右值，不能作为表达式的左边
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> i;&lt;span style="color:#75715e">//讲一个左值(a)设置为另一个左值(i)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> i1 &lt;span style="color:#f92672">=&lt;/span> GetValue();&lt;span style="color:#75715e">//GetValue()是一个右值，i是一个左值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//GetValue() = 5;//GetValue()是一个右值，不能作为表达式的左边，而表达式必须是一个可修改的左值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		GetRefValue()&lt;span style="color:#f92672">++&lt;/span>;&lt;span style="color:#75715e">//GetRefValue()是一个左值，可以作为表达式的左边 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">GetRefValue():10
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">GetRefValue():11
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">GetRefValue():12
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	SetValue(i);&lt;span style="color:#75715e">//i是一个左值，可以作为表达式的右边，用左值创建一个临时对象，并将其作为实参传递给函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	SetValue(&lt;span style="color:#ae81ff">10&lt;/span>);&lt;span style="color:#75715e">//10是一个右值，可以作为表达式的右边,即用右值创建一个临时对象，并将其作为实参传递给函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	SetValue1(i);&lt;span style="color:#75715e">//从左值创建一个左值引用，所以可以将左值i作为实参传递给函数SetValue1(int&amp;amp; value)，编译器会将i作为实参传递给函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//SetValue1(10); //编译出错：不能从右值创建一个左值引用，所以不能将右值10作为实参传递给函数SetValue1(int&amp;amp; value)，编译器会报错 //非const的引用，必须通过左值来初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	SetValueConst(i);&lt;span style="color:#75715e">//从左值创建一个const左值引用 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	SetValueConst(&lt;span style="color:#ae81ff">10&lt;/span>);&lt;span style="color:#75715e">//从右值创建一个const左值引用 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//int&amp;amp; a1 = 10;//非const的引用，必须通过左值来初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译器可能创建了一个带实际存储的临时变量(比如temp=10)，然后
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//const int&amp;amp; b1=temp;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> b1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">11&lt;/span>;&lt;span style="color:#75715e">//const的引用，还可以通过右值来初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="右值引用-rvalue-references--">右值引用 (rvalue references) —— &lt;code>&amp;amp;&amp;amp;&lt;/code>&lt;a class="anchor" href="#%e5%8f%b3%e5%80%bc%e5%bc%95%e7%94%a8-rvalue-references--">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>新语法&lt;/mark>：C++11 引入了 &lt;code>int&amp;amp;&amp;amp;&lt;/code>。&lt;/li>
&lt;li>&lt;mark>作用&lt;/mark>：它&lt;mark>专门&lt;/mark>用来绑定右值。
&lt;ul>
&lt;li>&lt;code>int&amp;amp;&amp;amp; a = 10;&lt;/code> 是合法的。&lt;/li>
&lt;li>它允许我们“拦截”那些即将销毁的临时对象。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>&lt;mark>意义何在？&lt;/mark>：这是为了&lt;mark>性能优化&lt;/mark>。既然右值是临时的，我们与其拷贝它的数据，不如直接“偷”走它的资源（这就是移动语义的基础）。&lt;/li>
&lt;/ul>
&lt;h1 id="实际应用函数重载">实际应用：函数重载&lt;a class="anchor" href="#%e5%ae%9e%e9%99%85%e5%ba%94%e7%94%a8%e5%87%bd%e6%95%b0%e9%87%8d%e8%bd%bd">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>场景演示&lt;/mark>：Cherno 展示了如何通过重载同一函数名，分别处理左值和右值：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name); &lt;span style="color:#75715e">// 接收左值和 const 右值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> name); &lt;span style="color:#75715e">// 专门接收右值（临时对象）
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>
&lt;p>解释&lt;/p></description></item><item><title>84跟踪内存的分配与释放</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/84%E8%B7%9F%E8%B8%AA%E5%86%85%E5%AD%98%E7%9A%84%E5%88%86%E9%85%8D%E4%B8%8E%E9%87%8A%E6%94%BE/</link><pubDate>Fri, 06 Mar 2026 17:08:25 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/84%E8%B7%9F%E8%B8%AA%E5%86%85%E5%AD%98%E7%9A%84%E5%88%86%E9%85%8D%E4%B8%8E%E9%87%8A%E6%94%BE/</guid><description>&lt;h1 id="核心原理重载全局-new">核心原理：重载全局 &lt;code>new&lt;/code>&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e5%8e%9f%e7%90%86%e9%87%8d%e8%bd%bd%e5%85%a8%e5%b1%80-new">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>原理&lt;/mark>：在 C++ 中，当你写 &lt;code>new Object()&lt;/code> 时，它实际上调用了一个名为 &lt;code>operator new&lt;/code> 的全局函数。&lt;/li>
&lt;li>&lt;mark>自定义拦截&lt;/mark>：你可以重写这个函数。编译器会优先使用你的自定义版本，而不是标准库提供的版本。&lt;/li>
&lt;li>&lt;mark>代码演示&lt;/mark>：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">new&lt;/span>(size_t size) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Allocating &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> size &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; bytes&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> malloc(size); &lt;span style="color:#75715e">// 最终还是要调用底层的内存分配
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="对应的-delete-重载">对应的 &lt;code>delete&lt;/code> 重载&lt;a class="anchor" href="#%e5%af%b9%e5%ba%94%e7%9a%84-delete-%e9%87%8d%e8%bd%bd">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>对称性&lt;/mark>：重载了 &lt;code>new&lt;/code> 就必须重载 &lt;code>delete&lt;/code>，否则可能会导致内存管理逻辑不一致。&lt;/li>
&lt;li>&lt;mark>代码实现&lt;/mark>：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">delete&lt;/span>(&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> memory, size_t size) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Freeing &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> size &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; bytes&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> free(memory);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;mark>注意&lt;/mark>：Cherno 提到现代 C++ 建议使用带 &lt;code>size&lt;/code> 参数的 &lt;code>delete&lt;/code> 版本，以便更精准地追踪。&lt;/li>
&lt;/ul>
&lt;h1 id="实战追踪总分配量-the-tracker">实战：追踪总分配量 (The Tracker)&lt;a class="anchor" href="#%e5%ae%9e%e6%88%98%e8%bf%bd%e8%b8%aa%e6%80%bb%e5%88%86%e9%85%8d%e9%87%8f-the-tracker">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>引入单例/全局状态&lt;/mark>：为了统计数据，Cherno 定义了一个简单的结构体来存储 &lt;code>TotalAllocated&lt;/code> 和 &lt;code>TotalFreed&lt;/code>。&lt;/li>
&lt;li>&lt;mark>逻辑&lt;/mark>：在 &lt;code>new&lt;/code> 里面让计数器增加，在 &lt;code>delete&lt;/code> 里面减少。&lt;/li>
&lt;li>&lt;mark>演示&lt;/mark>：通过创建一个 &lt;code>std::string&lt;/code> 或自己的 &lt;code>Entity&lt;/code> 类，观察控制台实时打印出的分配字节数。&lt;/li>
&lt;/ul>
&lt;h1 id="完整代码">完整代码&lt;a class="anchor" href="#%e5%ae%8c%e6%95%b4%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP84
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">AllocationMetrics&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> TotalAllocated &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> TotalFreed &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">uint32_t&lt;/span> &lt;span style="color:#a6e22e">CurrentUsage&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> TotalAllocated &lt;span style="color:#f92672">-&lt;/span> TotalFreed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> AllocationMetrics s_AllocationMetrics;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//重写operator new 的全局函数，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//链接器会转而链接这个函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">new&lt;/span>(size_t size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	s_AllocationMetrics.TotalAllocated &lt;span style="color:#f92672">+=&lt;/span> size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Allocating &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> size &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; bytes&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> malloc(size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//重写特定函数签名来获取特定的释放大小的信息
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">delete&lt;/span>(&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> memory, size_t size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	s_AllocationMetrics.TotalFreed &lt;span style="color:#f92672">+=&lt;/span> size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Freeing &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> size &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; bytes&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	free(memory);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Object&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x, y, z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">内存使用情况
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintMemoryUsage&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Memory Usage: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> s_AllocationMetrics.CurrentUsage() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; bytes.&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintMemoryUsage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Object&lt;span style="color:#f92672">*&lt;/span> obj &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Object;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//正好12字节，在 C++ 中，类/结构体本身不包含任何运行时开销。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Size of Object: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(Object) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintMemoryUsage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string s &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintMemoryUsage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;=========&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这行代码仍会分配12字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Object&lt;span style="color:#f92672">&amp;gt;&lt;/span> obj1 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>make_unique&lt;span style="color:#f92672">&amp;lt;&lt;/span>Object&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintMemoryUsage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;**********&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Object&lt;span style="color:#f92672">&amp;gt;&lt;/span> obj &lt;span style="color:#f92672">=&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>make_unique&lt;span style="color:#f92672">&amp;lt;&lt;/span>Object&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		PrintMemoryUsage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintMemoryUsage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Memory Usage: 0 bytes.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Allocating 12 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Size of Object: 12
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Memory Usage: 12 bytes.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Allocating 8 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Memory Usage: 20 bytes.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">=========
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Allocating 12 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Memory Usage: 32 bytes.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">**********
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Allocating 12 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Memory Usage: 44 bytes.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Freeing 12 bytes
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Memory Usage: 32 bytes.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="new">new&lt;a class="anchor" href="#new">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>设置断点在operator new函数里面的&lt;code>return malloc(size);&lt;/code>&lt;/li>
&lt;li>（Debug模式下）第二次进入断点，即&lt;code>std::string s = &amp;quot;Cherno&amp;quot;;&lt;/code>后进去，调用栈如下（从下往上）&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="img/ly-20260306220626154.png" alt="" />&lt;/p></description></item><item><title>82单例模式详解</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/82%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E8%AF%A6%E8%A7%A3/</link><pubDate>Fri, 06 Mar 2026 13:40:48 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/81-/82%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F%E8%AF%A6%E8%A7%A3/</guid><description>&lt;p>&lt;mark>单例模式 (Singleton)&lt;/mark>。单例的核心思想是：&lt;mark>在整个应用程序的生命周期中，某个类只存在一个实例。&lt;/mark>&lt;/p>
&lt;h1 id="什么是单例-the-concept">什么是单例？ (The Concept)&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af%e5%8d%95%e4%be%8b-the-concept">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>核心定义&lt;/mark>：单例是只有&lt;mark>单一实例&lt;/mark>的类。&lt;/li>
&lt;li>&lt;mark>应用场景&lt;/mark>：当你&lt;mark>需要一个全局访问点来管理某些资源&lt;/mark>时（如&lt;mark>随机数生成器、渲染器、数据库连接&lt;/mark>等）非常有用。&lt;/li>
&lt;li>&lt;mark>争议性&lt;/mark>：单例本质上是“披着类外壳的全局变量”，在某些开发者眼中这被视为一种“反模式”，但 Cherno 认为在特定场景下它非常高效。 &lt;del>把类当做命名空间来调用某些函数&lt;/del>&lt;/li>
&lt;li>如果你只有一个实例，你那实际有的就只是一组数据，以及一些配套功能&lt;/li>
&lt;li>替代单例：属于某个命名空间的函数、全局变量、某个与源文件关联的静态变量、特定的C++源文件&lt;/li>
&lt;li>单例的生命周期和应用程序的一样&lt;/li>
&lt;/ul>
&lt;h1 id="基础实现逻辑-basic-implementation">基础实现逻辑 (Basic Implementation)&lt;a class="anchor" href="#%e5%9f%ba%e7%a1%80%e5%ae%9e%e7%8e%b0%e9%80%bb%e8%be%91-basic-implementation">#&lt;/a>&lt;/h1>
&lt;p>单例模式主要依靠以下三个步骤实现：&lt;/p>
&lt;ol>
&lt;li>&lt;mark>私有化构造函数&lt;/mark>：通过 &lt;code>private&lt;/code> 构造函数防止外部通过 &lt;code>new&lt;/code> 或直接声明来创建新实例。&lt;/li>
&lt;li>&lt;mark>禁用拷贝构造&lt;/mark>：删除拷贝构造函数（&lt;code>ClassName(const ClassName&amp;amp;) = delete;&lt;/code>），确保无法通过复制来产生第二个实例。&lt;/li>
&lt;li>&lt;mark>静态访问点&lt;/mark>：提供一个静态方法（通常命名为 &lt;code>Get()&lt;/code>），返回那个唯一的静态实例。&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP82
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Singleton&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Singleton(&lt;span style="color:#66d9ef">const&lt;/span> Singleton&lt;span style="color:#f92672">&amp;amp;&lt;/span>) &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">delete&lt;/span>;&lt;span style="color:#75715e">//禁止拷贝
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">static&lt;/span> Singleton&lt;span style="color:#f92672">&amp;amp;&lt;/span> Get()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> s_Instance;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Function&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Function&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> m_Member &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3.4f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Singleton() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">static&lt;/span> Singleton s_Instance;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//定义 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//1. 在全局/静态内存区分配 sizeof(Singleton) 字节的空间。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//2. 在程序启动时，自动调用 Singleton 的构造函数来初始化这块空间。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//由于你使用了作用域解析符 Singleton::，编译器认为这行代码依然属于 Singleton 类的范畴
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>Singleton Singleton&lt;span style="color:#f92672">::&lt;/span>s_Instance;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这种写法，调用了Singleton类的复制构造函数，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//拷贝了所有成员，并创建了一个新的实例（违背单例本意）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//类定义中Singleton(const Singleton&amp;amp;) = delete;//禁止拷贝
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Singleton instance = Singleton::Get();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> instantce &lt;span style="color:#f92672">=&lt;/span> Singleton&lt;span style="color:#f92672">::&lt;/span>Get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Singleton&lt;span style="color:#f92672">::&lt;/span>Get().Function();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="现代-c-的最佳实践-the-best-way">现代 C++ 的最佳实践 (The Best Way)&lt;a class="anchor" href="#%e7%8e%b0%e4%bb%a3-c-%e7%9a%84%e6%9c%80%e4%bd%b3%e5%ae%9e%e8%b7%b5-the-best-way">#&lt;/a>&lt;/h1>
&lt;p>Cherno 演示了最简洁且&lt;mark>线程安全&lt;/mark>的单例写法（C++11 及更高版本）：&lt;/p></description></item><item><title>80加速字符串操作</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/80%E5%8A%A0%E9%80%9F%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%93%8D%E4%BD%9C/</link><pubDate>Fri, 06 Mar 2026 10:16:18 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/80%E5%8A%A0%E9%80%9F%E5%AD%97%E7%AC%A6%E4%B8%B2%E6%93%8D%E4%BD%9C/</guid><description>&lt;h1 id="附常量字符串">附：常量字符串&lt;a class="anchor" href="#%e9%99%84%e5%b8%b8%e9%87%8f%e5%ad%97%e7%ac%a6%e4%b8%b2">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Yan Chernikov&amp;#34;&lt;/span>;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="关于空字符">关于空字符&lt;a class="anchor" href="#%e5%85%b3%e4%ba%8e%e7%a9%ba%e5%ad%97%e7%ac%a6">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>右侧的字面量 &amp;ldquo;Yan Chernikov&amp;rdquo;(13个看得见的字符) 在内存（常量区）中以 \0 结尾。&lt;/li>
&lt;li>左侧的 std::string 对象 会在堆上申请空间，并把这 13 个字符拷贝过去。&lt;/li>
&lt;li>关键点：std::string 内部实现总是会额外多分配一个字节来存储这个 \0。这是为了确保当你调用 name.c_str() 时，能返回一个符合 C 语言标准的、以空字符结尾的字符串。&lt;/li>
&lt;/ul>
&lt;h2 id="关于赋值">关于赋值&lt;a class="anchor" href="#%e5%85%b3%e4%ba%8e%e8%b5%8b%e5%80%bc">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>字面量字符串是一个const char[N]类型的数组&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>
&lt;p>数组退化 (Array-to-pointer decay)：
字符串字面量首先从 const char[14] 退化为指向首元素的指针 const char* 。
&lt;img src="img/ly-20260306105916518.png" alt="" />&lt;/p>
&lt;/li>
&lt;li>
&lt;p>调用构造函数(Implicit Constructor Call)：
std::string 类有一个接收 const char* 参数的构造函数。由于该构造函数没有被标记为 explicit，编译器会自动调用它来创建一个临时的 std::string 对象。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>内存分配(The &amp;ldquo;Cost&amp;rdquo;)：
正如 Cherno 在第 80 集中强调的，这个隐式转换并不只是“换个名字”，它会在 堆（Heap）上分配内存，并将字符串内容拷贝进去。&lt;/p>
&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>name.size()：返回 13（不计入 \0）。&lt;/li>
&lt;li>name[13]：在 C++11 及以后的标准中，访问这个位置是合法的，它会返回 \0。&lt;/li>
&lt;/ul>
&lt;h1 id="调试注意">调试注意&lt;a class="anchor" href="#%e8%b0%83%e8%af%95%e6%b3%a8%e6%84%8f">#&lt;/a>&lt;/h1>
&lt;p>本篇测试均在Release模式下测试，因为Debug模式下由于调试需要会有其他的内存分配&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP80
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">uint32_t&lt;/span> s_AllocaCount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//重载new运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span> &lt;span style="color:#a6e22e">new&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>size_t size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	s_AllocaCount&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	printf(&lt;span style="color:#e6db74">&amp;#34;Allocating %zu bytes of memory.&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>, size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> malloc(size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//std::string 在栈上预留了 15 字节 的缓冲区，无需堆分配。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Yan Chernikov&amp;#34;&lt;/span>;&lt;span style="color:#75715e">//13个字符 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Debug模式下输出Allocating 8 bytes of memory.（调试代理、迭代器调试需要的8字节）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Release模式下没有输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string name1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;012345678901234567891&amp;#34;&lt;/span>;&lt;span style="color:#75715e">//21个字符 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*现代 CPU 处理内存时，如果地址是 16 或 32 的倍数，效率最高。以下是输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	Allocating 32 bytes of memory.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="1-问题所在不必要的内存分配">1. 问题所在：不必要的内存分配&lt;a class="anchor" href="#1-%e9%97%ae%e9%a2%98%e6%89%80%e5%9c%a8%e4%b8%8d%e5%bf%85%e8%a6%81%e7%9a%84%e5%86%85%e5%ad%98%e5%88%86%e9%85%8d">#&lt;/a>&lt;/h1>
&lt;p>传统的 &lt;code>std::string&lt;/code> 在进行截取、传递或操作时，往往会触发&lt;mark>动态内存分配（Heap Allocation）&lt;/mark>。&lt;/p></description></item><item><title>79通过多线程提升性能</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/79%E9%80%9A%E8%BF%87%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8F%90%E5%8D%87%E6%80%A7%E8%83%BD/</link><pubDate>Thu, 05 Mar 2026 23:03:01 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/79%E9%80%9A%E8%BF%87%E5%A4%9A%E7%BA%BF%E7%A8%8B%E6%8F%90%E5%8D%87%E6%80%A7%E8%83%BD/</guid><description>&lt;p>&lt;em>如何利用 &lt;code>std::async&lt;/code> 让 C++ 运行更快&lt;/em>&lt;/p>
&lt;p>这一集的核心在于展示如何通过&lt;mark>多线程异步&lt;/mark>处理来&lt;mark>优化原本串行执行的耗时&lt;/mark>操作，主要讲解了 &lt;code>std::async&lt;/code> 的用法及其与 &lt;code>std::future&lt;/code> 的配合。&lt;/p>
&lt;h1 id="1-问题背景与性能现状">1. 问题背景与性能现状&lt;a class="anchor" href="#1-%e9%97%ae%e9%a2%98%e8%83%8c%e6%99%af%e4%b8%8e%e6%80%a7%e8%83%bd%e7%8e%b0%e7%8a%b6">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>串行执行的局限性&lt;/mark>：Cherno 首先展示了一个简单的示例程序（通常是加载资源或执行大量计算）。在单线程环境下，这些任务必须一个接一个地完成，导致总耗时是所有任务时间的总和。&lt;/li>
&lt;li>&lt;mark>性能瓶颈&lt;/mark>：如果其中一个任务（如 &lt;code>LoadFunction&lt;/code>）非常耗时，整个程序就会被阻塞，无法利用现代 CPU 的多核优势。&lt;/li>
&lt;/ul>
&lt;blockquote class='book-hint '>
&lt;p>如今的游戏加载非常长，原因是需要加载的资源太多，加载过程不仅仅是从磁盘读取文件，涉及解压文件、将其发送到图形处理器、根据特定情况特定转换，但每一项资源、纹理、模型通常相互独立，即它们是多线程的理想选择&lt;/p>&lt;/blockquote>&lt;h1 id="2-引入-stdasync">2. 引入 &lt;code>std::async&lt;/code>&lt;a class="anchor" href="#2-%e5%bc%95%e5%85%a5-stdasync">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>&lt;mark>什么是 &lt;code>std::async&lt;/code>&lt;/mark>：它是 C++11 引入的一个高级 API，用于启动异步任务。它比手动创建 &lt;code>std::thread&lt;/code> 更简单，因为它能自动处理线程的创建和管理。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>&lt;code>std::launch&lt;/code> 策略&lt;/mark>：&lt;/p>
&lt;ul>
&lt;li>&lt;code>std::launch::async&lt;/code>：强制在不同线程中异步运行。&lt;/li>
&lt;li>&lt;code>std::launch::deferred&lt;/code>：延迟执行，直到调用 &lt;code>get()&lt;/code> 或 &lt;code>wait()&lt;/code> 时才在当前线程运行。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>&lt;mark>基本语法&lt;/mark>：展示如何将普通函数调用包装进 &lt;code>std::async&lt;/code> 中。&lt;/p>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP79
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;future&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>mutex mtx;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> meshes;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">LoadMesh&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> i)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Loading mesh...[&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> i &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;]&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//加锁-&amp;gt;互斥锁
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//该锁在当前作用域结束时自动释放 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>lock_guard&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>mutex&lt;span style="color:#f92672">&amp;gt;&lt;/span> lock(mtx);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//模拟：将加载的网格ID添加到共享资源中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	meshes.push_back(i);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Mesh Added: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> i &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">LoadMeshes&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//因为这里的异步任务，即LoadMesh函数返回void，所以我们使用std::future&amp;lt;void&amp;gt;来存储这些异步任务的结果。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>future&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;gt;&lt;/span> futures;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">15&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// std::async ：立即在后台开启一个新的线程，去执行 LoadMesh(i) 这个函数，不要阻塞我当前的进度。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1. 但是，因为它返回的 std::future 没有赋值给任何变量，它会在这一行结束时立刻析构。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//2. std::future 的析构函数逻辑是：“等一下！任务还没跑完，我不能死，我要阻塞主线程直到子线程结束。”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//3. 所以，最终导致主线程在每次调用 std::async 后都被阻塞，等待子线程完成，才继续下一次循环。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//std::async(std::launch::async, LoadMesh, i);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">// 将 future 存入 vector，防止它立即析构
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//在单独线程中加载网格
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		futures.push_back(std&lt;span style="color:#f92672">::&lt;/span>async(std&lt;span style="color:#f92672">::&lt;/span>launch&lt;span style="color:#f92672">::&lt;/span>async, LoadMesh, i));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">LoadMeshesSync&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">15&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		LoadMesh(i);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#define ASYNC 1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#if ASYNC 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	LoadMeshes();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#else
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	LoadMeshesSync();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/* Mesh Added:顺序是随机的，因为可能某线程执行std::lock_guard&amp;lt;std::mutex&amp;gt; lock(mtx);这行代码前，被其他线程抢先
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Loading mesh...[10Loading mesh...[11]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Loading mesh...[12]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Loading mesh...[13]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Loading mesh...[14]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Mesh Added: 11
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Mesh Added: 10
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Mesh Added: 12
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Mesh Added: 13
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Mesh Added: 14
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>通过parallel Stacks查看不同线程栈信息&lt;/p></description></item><item><title>78存储任意类型数据</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/78%E5%AD%98%E5%82%A8%E4%BB%BB%E6%84%8F%E7%B1%BB%E5%9E%8B%E6%95%B0%E6%8D%AE/</link><pubDate>Wed, 04 Mar 2026 23:14:28 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/78%E5%AD%98%E5%82%A8%E4%BB%BB%E6%84%8F%E7%B1%BB%E5%9E%8B%E6%95%B0%E6%8D%AE/</guid><description>&lt;p>介绍了 &lt;mark>C++17&lt;/mark> 引入的 &lt;code>std::any&lt;/code>。它是一个可以存储&lt;mark>绝对任何类型&lt;/mark>变量的容器（本质上是一个&lt;mark>类型安全的 &lt;code>void*&lt;/code>&lt;/mark>），但与 &lt;code>void*&lt;/code> 不同的是，它会处理对象的构造和析构。&lt;/p>
&lt;h1 id="1-基本用法">1. 基本用法&lt;a class="anchor" href="#1-%e5%9f%ba%e6%9c%ac%e7%94%a8%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>包含头文件&lt;/mark>：&lt;code>#include &amp;lt;any&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;mark>赋值&lt;/mark>：你可以随意给它赋值，不需要预先定义类型。&lt;/li>
&lt;/ul>
&lt;h1 id="2-如何提取数据stdany_cast">2. 如何提取数据：std::any_cast&lt;a class="anchor" href="#2-%e5%a6%82%e4%bd%95%e6%8f%90%e5%8f%96%e6%95%b0%e6%8d%aestdany_cast">#&lt;/a>&lt;/h1>
&lt;p>由于 &lt;code>any&lt;/code> 可以是任何东西，你必须使用 &lt;code>std::any_cast&lt;/code> 并指定类型来取回数据：&lt;/p>
&lt;ul>
&lt;li>&lt;mark>按值取回&lt;/mark>：&lt;code>std::any_cast&amp;lt;int&amp;gt;(data)&lt;/code>。如果类型不匹配，会抛出 &lt;code>std::bad_any_cast&lt;/code> 异常。&lt;/li>
&lt;li>&lt;mark>按引用取回&lt;/mark>：为了性能，通常建议取引用或指针，避免拷贝。&lt;/li>
&lt;/ul>
&lt;h2 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP78
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;any&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;variant&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>any data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">char&lt;/span> name[] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		data &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)name;&lt;span style="color:#75715e">// 将 name 数组的地址存储在 data 中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} &lt;span style="color:#75715e">// name 数组在这里被销毁了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 此时 data 内部存储的指针指向了一个已经失效的内存地址（野指针）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3.45&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//1. 构造临时对象：std::string 首先根据 &amp;#34;Cherno&amp;#34; 构造自己（这次会有一次内存分配和拷贝）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. 调用 operator=：这个临时对象被传给 std::any::operator=。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3. 内部转换：std::any 内部会检测到这是一个右值（临时对象），它会调用 std::string 的移动构造函数，在自己的内部空间（或它在堆上新开辟的空间）重建这个 string。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//4. 释放临时对象：原本的临时对象变成“空壳”，随后被销毁。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	data &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);&lt;span style="color:#75715e">// 现在 data 内部存储的是一个 std::string 对象，之前的指针已经被覆盖了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 这种方式直接在 data 的内部空间构造 string，效率最高
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	data &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>make_any&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//获取值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string string &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>any_cast&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span>(data);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> string &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;haha&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//运行时报错,data此时是一个const char*，不是std::string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::string string2 = std::any_cast&amp;lt;std::string&amp;gt;(data);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::cout &amp;lt;&amp;lt; string2 &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>variant&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>, std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> var;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	var &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	var &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string string3 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>get&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span>(var);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> string3 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//运行正常，输出&amp;#34;Hello&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="3-工作原理与性能开销">3. 工作原理与性能开销&lt;a class="anchor" href="#3-%e5%b7%a5%e4%bd%9c%e5%8e%9f%e7%90%86%e4%b8%8e%e6%80%a7%e8%83%bd%e5%bc%80%e9%94%80">#&lt;/a>&lt;/h1>
&lt;p>这是本集的重点，Cherno 解释了为什么不能滥用 &lt;code>std::any&lt;/code>：&lt;/p></description></item><item><title>77在单变量中存储多种类型数据</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/77%E5%9C%A8%E5%8D%95%E5%8F%98%E9%87%8F%E4%B8%AD%E5%AD%98%E5%82%A8%E5%A4%9A%E7%A7%8D%E7%B1%BB%E5%9E%8B%E6%95%B0%E6%8D%AE/</link><pubDate>Wed, 04 Mar 2026 19:48:33 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/77%E5%9C%A8%E5%8D%95%E5%8F%98%E9%87%8F%E4%B8%AD%E5%AD%98%E5%82%A8%E5%A4%9A%E7%A7%8D%E7%B1%BB%E5%9E%8B%E6%95%B0%E6%8D%AE/</guid><description>&lt;h1 id="核心概念">核心概念&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5">#&lt;/a>&lt;/h1>
&lt;p>本集介绍了 &lt;mark>C++17&lt;/mark> 引入的 &lt;code>std::variant&lt;/code>。它是一个&lt;mark>类型安全的联合体 (Type-safe Union)&lt;/mark>，允许&lt;mark>一个变量在不同时间存储预定义的一组类型中的任意一种&lt;/mark> &lt;del>比如我接收一个参数可能是字符串或者整数&amp;ndash;因为也许我接受的参数来自命令行参数&lt;/del> 。&lt;/p>
&lt;h1 id="1-为什么需要-stdvariant">1. 为什么需要 std::variant？&lt;a class="anchor" href="#1-%e4%b8%ba%e4%bb%80%e4%b9%88%e9%9c%80%e8%a6%81-stdvariant">#&lt;/a>&lt;/h1>
&lt;p>在 C++17 之前，如果你想让一个变量既能存 &lt;code>string&lt;/code> 也能存 &lt;code>int&lt;/code>：&lt;/p>
&lt;ul>
&lt;li>&lt;mark>使用 &lt;code>union&lt;/code>&lt;/mark>：传统的 &lt;code>union&lt;/code> 不够安全，它不会追踪当前存储的是哪种类型，且处理复杂类型（如 &lt;code>std::string&lt;/code>）时非常麻烦。&lt;/li>
&lt;li>&lt;mark>使用 &lt;code>std::variant&lt;/code>&lt;/mark>：它解决了这些问题。它知道自己当前存的是什么，并且会自动处理复杂类型的构造和析构。&lt;/li>
&lt;/ul>
&lt;h1 id="2-基本用法">2. 基本用法&lt;a class="anchor" href="#2-%e5%9f%ba%e6%9c%ac%e7%94%a8%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>包含头文件&lt;/mark>：&lt;code>#include &amp;lt;variant&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;mark>声明与赋值&lt;/mark>：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//列出可能的数据类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>variant&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string, &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> data; 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>; &lt;span style="color:#75715e">// 存储 string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">24&lt;/span>; &lt;span style="color:#75715e">// 存储 int
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;mark>注意&lt;/mark>：&lt;code>variant&lt;/code> 的大小等于其最大候选类型的大小加上一些存储索引的开销（类似于 &lt;code>struct&lt;/code>），这与 &lt;code>union&lt;/code> 共享内存的特性类似。&lt;/li>
&lt;/ul>
&lt;h1 id="3-如何读取数据">3. 如何读取数据&lt;a class="anchor" href="#3-%e5%a6%82%e4%bd%95%e8%af%bb%e5%8f%96%e6%95%b0%e6%8d%ae">#&lt;/a>&lt;/h1>
&lt;p>由于 &lt;code>variant&lt;/code> 是类型安全的，你不能直接访问，有几种主要方式：&lt;/p>
&lt;ul>
&lt;li>&lt;mark>&lt;code>std::get&amp;lt;T&amp;gt;(var)&lt;/code>&lt;/mark>：指定类型获取。如果类型不匹配，会抛出 &lt;code>std::bad_variant_access&lt;/code> 异常。&lt;/li>
&lt;li>&lt;mark>&lt;code>std::get_if&amp;lt;T&amp;gt;(&amp;amp;var)&lt;/code>&lt;/mark>：&lt;mark>（推荐方式）&lt;/mark> 传入地址。如果类型匹配则返回指针，否则返回 &lt;code>nullptr&lt;/code>。这种方式不会抛出异常，适合配合 &lt;code>if&lt;/code> 使用。&lt;/li>
&lt;li>&lt;mark>&lt;code>std::variant::index()&lt;/code>&lt;/mark>：返回当前存储类型的索引（从 0 开始）。&lt;/li>
&lt;/ul>
&lt;h2 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP77
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;variant&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>variant&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string, &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>get&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span>(data) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//data = 3.45;//编译报错，不通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>get&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(data) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//std::cout &amp;lt;&amp;lt; std::get&amp;lt;std::string&amp;gt;(data) &amp;lt;&amp;lt; std::endl;//运行时抛出异常
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	data &lt;span style="color:#f92672">=&lt;/span> true;&lt;span style="color:#75715e">//隐式转换，true转为1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>get&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(data) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//运行时抛出异常
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Unhandled exception at 0x763A2CA4 in HelloWorld62.exe: Microsoft C++ exception: std::bad_variant_access at memory location 0x012FFA2C.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::cout &amp;lt;&amp;lt; std::get&amp;lt;std::string&amp;gt;(data) &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如上定义该变量时,std::string对应的索引映射为0，int对应的索引映射为1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data.index() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//get_if函数接受一个地址，返回一个指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果当前 variant 存的数据类型匹配，它返回指向该数据的指针。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果类型不匹配，它返回 nullptr（空指针），而不会让程序崩溃。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">auto&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>get_if&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>data))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> v &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>value;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;it&amp;#39;s a string:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">auto&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>get_if&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>data))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> v &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>value;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;it&amp;#39;s an int:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//union 的特点是所有成员共享同一块内存。如果你给 age 赋值，就会覆盖掉 name 的内存。如果此时 name 原本存有字符串，它的析构函数将无法正确释放内存，导致内存泄漏或崩溃。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//注意：在现代 C++ 中，如果你要在 union 里放 std::string，你必须手动定义 union 的构造和析构函数。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">union&lt;/span> &lt;span style="color:#a6e22e">TestS&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>string name;&lt;span style="color:#75715e">//28字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">int&lt;/span> age;&lt;span style="color:#75715e">//4字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;union======size===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>string) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//28字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//4字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(TestS) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//28字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;variant======size===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//32=28+4，所以基本上创建了struct，或者说用于存储两种数据类型的空间；所以union更高效，而variant安全性更高
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(data) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//32
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="data--false分析">&lt;code>data = false;&lt;/code>分析&lt;a class="anchor" href="#data--false%e5%88%86%e6%9e%90">#&lt;/a>&lt;/h3>
&lt;p>当执行 &lt;code>data = false;&lt;/code> 时，发生了&lt;mark>隐式类型转换（Implicit Conversion）&lt;/mark>。&lt;/p></description></item><item><title>76可选数据处理</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/76%E5%8F%AF%E9%80%89%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86/</link><pubDate>Wed, 04 Mar 2026 13:25:37 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/76%E5%8F%AF%E9%80%89%E6%95%B0%E6%8D%AE%E5%A4%84%E7%90%86/</guid><description>&lt;h1 id="核心概念">核心概念&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e6%a6%82%e5%bf%b5">#&lt;/a>&lt;/h1>
&lt;p>本集主要讨论 &lt;mark>C++17&lt;/mark> 引入的 &lt;code>std::optional&lt;/code>。它提供了一种优雅的方式来处理==“值可能存在，也可能不存在”==的情况，避免了使用魔术数字（如 &lt;code>-1&lt;/code>）、空字符串或布尔标志位等不直观的方法。&lt;/p>
&lt;h1 id="1-传统处理方式的弊端">1. 传统处理方式的弊端&lt;a class="anchor" href="#1-%e4%bc%a0%e7%bb%9f%e5%a4%84%e7%90%86%e6%96%b9%e5%bc%8f%e7%9a%84%e5%bc%8a%e7%ab%af">#&lt;/a>&lt;/h1>
&lt;p>在没有 &lt;code>std::optional&lt;/code> 之前，如果一个函数可能无法返回有效数据，程序员通常会：&lt;/p>
&lt;ul>
&lt;li>&lt;mark>返回特殊值&lt;/mark>：例如找不到文件时返回空字符串 &lt;code>&amp;quot;&amp;quot;&lt;/code>。但问题是，有时空字符串本身可能也是合法的返回结果，导致二义性。&lt;/li>
&lt;li>&lt;mark>使用布尔标记&lt;/mark>：通过引用的方式传出数据，函数返回 &lt;code>bool&lt;/code> 表示是否成功。这种方式虽然可行，但代码写起来比较琐碎。
&lt;ul>
&lt;li>函数返回一个布尔值（true 或 false）来表示操作是否成功，而实际的数据通过“输出参数”（通常是引用或指针）来传递。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="2-stdoptional-的基本用法">2. std::optional 的基本用法&lt;a class="anchor" href="#2-stdoptional-%e7%9a%84%e5%9f%ba%e6%9c%ac%e7%94%a8%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;p>&lt;code>std::optional&lt;/code> 像是一个容器，它要么包含一个指定类型的值，要么为空（&lt;code>std::nullopt&lt;/code>）。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>包含头文件&lt;/mark>：&lt;code>#include &amp;lt;optional&amp;gt;&lt;/code>&lt;/li>
&lt;li>&lt;mark>读取文件示例&lt;/mark>：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-C++" data-lang="C++">&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>optional&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> ReadFileAsString(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filepath) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>ifstream stream(filepath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (stream) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>string result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 读取文件内容...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">return&lt;/span> result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">//return {};// ai提示return std::nullopt; // 显式表示没有值 [00:05:00]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="完整代码">完整代码&lt;a class="anchor" href="#%e5%ae%8c%e6%95%b4%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//同文件夹下：data.txt
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>Data&lt;span style="color:#f92672">!&lt;/span>Hello&lt;span style="color:#f92672">!&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP76
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;fstream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//C++17引入了std::optional类型，可以用来表示一个值可能存在也可能不存在的情况。它提供了一种更安全和更清晰的方式来处理函数返回值，避免了使用引用参数来传递成功与否的信息。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;optional&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;sstream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">//读取文件内容需要使用std::stringstream
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//方法1：通过引用参数返回成功与否
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//std::string ReadFileAsString(const std::string&amp;amp; filePath,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//bool&amp;amp; outSuccess)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>optional&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> ReadFileAsString(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> filePath)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>ifstream stream(filePath);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (stream)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>stringstream result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		result &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> stream.rdbuf();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//read file
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		stream.close();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> result.str();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> {};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在内存中，std::optional&amp;lt;T&amp;gt; 通常包含两个主要部分：
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//1. 一块足够大的内存空间：用来存放类型为 T 的值（在你的例子中是 std::string）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. 一个布尔标记（bool flag）：记录这个盒子现在是“满的”还是“空的”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>optional&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> data &lt;span style="color:#f92672">=&lt;/span> ReadFileAsString(&lt;span style="color:#e6db74">&amp;#34;data.txt&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>optional&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> data1 &lt;span style="color:#f92672">=&lt;/span> ReadFileAsString(&lt;span style="color:#e6db74">&amp;#34;data1.txt&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果是读取参数，那就是指定默认值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::string value = data.value_or(&amp;#34;default value&amp;#34;);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//或者if(data)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span>(data.has_value())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//数据读取
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;File content: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data.value() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;File content: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> string &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Failed to read file.&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (data1.has_value())
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//数据读取
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>data1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;File content: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data1.value() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;File content: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> string &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Failed to read file(data1.txt).&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">File content: Data!Hello!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">File content: Data!Hello!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Failed to read file(data1.txt).
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="3-如何检查与获取值">3. 如何检查与获取值&lt;a class="anchor" href="#3-%e5%a6%82%e4%bd%95%e6%a3%80%e6%9f%a5%e4%b8%8e%e8%8e%b7%e5%8f%96%e5%80%bc">#&lt;/a>&lt;/h1>
&lt;p>调用返回 &lt;code>std::optional&lt;/code> 的函数后，有几种处理方式：&lt;/p></description></item><item><title>74性能基准测试指南</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/74%E6%80%A7%E8%83%BD%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E6%8C%87%E5%8D%97/</link><pubDate>Tue, 03 Mar 2026 13:47:24 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/74%E6%80%A7%E8%83%BD%E5%9F%BA%E5%87%86%E6%B5%8B%E8%AF%95%E6%8C%87%E5%8D%97/</guid><description>&lt;ul>
&lt;li>利用 C++ 对象的生命周期（析构函数）来自动化测量任务。&lt;/li>
&lt;li>处理一个对性能要求很高的部分时，或者测试刚学到的新技术，此时想比较性能&lt;/li>
&lt;li>本章节讲解如何实际测量C++代码的性能&lt;/li>
&lt;/ul>
&lt;h1 id="测试循环所需时间">测试循环所需时间&lt;a class="anchor" href="#%e6%b5%8b%e8%af%95%e5%be%aa%e7%8e%af%e6%89%80%e9%9c%80%e6%97%b6%e9%97%b4">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP74
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Timer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Timer()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">::&lt;/span>now();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Timer()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">auto&lt;/span> endTimepoint &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">::&lt;/span>now();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//算出起始时间的微秒数 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">auto&lt;/span> start &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>time_point_cast&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>microseconds&lt;span style="color:#f92672">&amp;gt;&lt;/span>(m_StartTimepoint).time_since_epoch().count();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//算出结束时间的微秒数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">auto&lt;/span> end &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>time_point_cast&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>microseconds&lt;span style="color:#f92672">&amp;gt;&lt;/span>(endTimepoint).time_since_epoch().count();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//算出持续时间
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">auto&lt;/span> duration &lt;span style="color:#f92672">=&lt;/span> end &lt;span style="color:#f92672">-&lt;/span> start;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//将持续时间转换为毫秒并输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">double&lt;/span> ms &lt;span style="color:#f92672">=&lt;/span> duration &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">0.001&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> duration &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;us (&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> ms &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ms)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>time_point&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">&amp;gt;&lt;/span> m_StartTimepoint;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Timer timer; &lt;span style="color:#75715e">// 创建一个 Timer 对象，开始计时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">1000000&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			value &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//__debugbreak() 是 MSVC (Windows) 特有的编译器内置函数，会在这里中断程序，进入调试器，方便我们查看变量的值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//正式运行程序时也会中断甚至发生异常
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	__debugbreak();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>先设置断点，然后进入反汇编查看&lt;/p></description></item><item><title>73动态类型转换(dynamic_cast)</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/73%E5%8A%A8%E6%80%81%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2dynamic_cast/</link><pubDate>Tue, 03 Mar 2026 11:09:49 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/73%E5%8A%A8%E6%80%81%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2dynamic_cast/</guid><description>&lt;h1 id="引入什么是-casting">引入：什么是 Casting？&lt;a class="anchor" href="#%e5%bc%95%e5%85%a5%e4%bb%80%e4%b9%88%e6%98%af-casting">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>背景：在 C++ 中，我们经常需要在父类和子类指针之间转换。&lt;/li>
&lt;li>痛点：传统的 C 风格转换 &lt;code>(Player*)entity&lt;/code> 或 &lt;code>static_cast&lt;/code> 是“强行”转换。编译器完全信任你，即使你把一个“敌人”对象强行转成“玩家”对象，它也不会报错，但这会导致程序在运行时崩溃。&lt;/li>
&lt;/ul>
&lt;h1 id="dynamic-cast-的特殊性">Dynamic Cast 的特殊性&lt;a class="anchor" href="#dynamic-cast-%e7%9a%84%e7%89%b9%e6%ae%8a%e6%80%a7">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>一针见血的定义：&lt;code>dynamic_cast&lt;/code> 是专门用于&lt;mark>继承体系&lt;/mark>中的&lt;mark>安全转换&lt;/mark>。&lt;/li>
&lt;li>运行时检查 (RTTI &lt;del>运行时类型信息&lt;/del> )：它不像其他转换在编译时完成，而是在&lt;mark>程序运行时&lt;/mark>去检查这个对象“到底是不是”你要转的那个类型。&lt;/li>
&lt;li>返回值逻辑
&lt;ul>
&lt;li>如果转换成功：返回有效的指针。&lt;/li>
&lt;li>如果转换失败（类型不匹配）：返回 &lt;code>NULL&lt;/code> (或 &lt;code>nullptr&lt;/code>)。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="核心前置条件虚函数表">核心前置条件：虚函数表&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e5%89%8d%e7%bd%ae%e6%9d%a1%e4%bb%b6%e8%99%9a%e5%87%bd%e6%95%b0%e8%a1%a8">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>关键约束：要使用 &lt;code>dynamic_cast&lt;/code>，你的类必须是多态的 (Polymorphic)。&lt;/li>
&lt;li>原理：这意味着基类必须至少有一个 虚函数 (Virtual Function)。&lt;/li>
&lt;li>底层逻辑：&lt;code>dynamic_cast&lt;/code> 依赖于 RTTI (Run-Time Type Information)，而 RTTI 信息存储在虚函数表 (vtable) 中。如果类没有虚函数，就没有 RTTI，编译器会直接报错。&lt;/li>
&lt;/ul>
&lt;h1 id="代码实战演练">代码实战演练&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e5%ae%9e%e6%88%98%e6%bc%94%e7%bb%83">#&lt;/a>&lt;/h1>
&lt;p>Cherno 演示了一个经典的场景：&lt;/p>
&lt;ul>
&lt;li>基类：&lt;code>Entity&lt;/code>&lt;/li>
&lt;li>子类：&lt;code>Player&lt;/code> 和 &lt;code>Enemy&lt;/code>&lt;/li>
&lt;li>场景：你有一个 &lt;code>Entity*&lt;/code> 指针，你想知道它指向的到底是&lt;code>Player&lt;/code> 还是 &lt;code>Enemy&lt;/code>。&lt;/li>
&lt;li>写法：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP73
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">virtual&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> PrintName() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Player&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Entity
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Enemy&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Entity
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Player&lt;span style="color:#f92672">*&lt;/span> player &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Player();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> e &lt;span style="color:#f92672">=&lt;/span> player;&lt;span style="color:#75715e">//隐式转换，Player* 转换为 Entity*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> actuallyEnemy &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Enemy();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> actuallyPlayer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Player();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Player* p = e;//错误，Entity* 转换为 Player*，需要显示转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Player&lt;span style="color:#f92672">*&lt;/span> p &lt;span style="color:#f92672">=&lt;/span> (Player&lt;span style="color:#f92672">*&lt;/span>)actuallyEnemy;&lt;span style="color:#75715e">//不安全的转换，Enemy* 转换为 Player*，编译器允许，但运行时会出问题；如果访问Player和Entity共有的成员，可能不会出问题，但如果访问Player特有的成员，就会出问题，因为actuallyEnemy实际上是一个Enemy对象，而不是Player对象。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Player&lt;span style="color:#f92672">*&lt;/span> p1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">static_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Player&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(actuallyEnemy);&lt;span style="color:#75715e">//和上面的显示转换一样，属于不安全的转换 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//actuallyEnemy指向的类必须是多态的，在 C++ 的设计哲学里，非多态类确实没有存储运行时的类型信息。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Player&lt;span style="color:#f92672">*&lt;/span> p2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">dynamic_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Player&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(actuallyEnemy);&lt;span style="color:#75715e">//安全的转换，运行时会检查actuallyEnemy是否实际上是一个Player对象，如果是，则返回指向Player对象的指针；如果不是，则返回nullptr。由于actuallyEnemy实际上是一个Enemy对象，所以p2将被赋值为nullptr。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Player&lt;span style="color:#f92672">*&lt;/span> p3 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">dynamic_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Player&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(actuallyPlayer);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (p2)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;actuallyEnemy is a Player.&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;actuallyEnemy is NOT a Player.&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span>(p3)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;actuallyPlayer is a Player.&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;actuallyPlayer is NOT a Player.&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">actuallyEnemy is NOT a Player.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">actuallyPlayer is a Player.
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="性能代价-the-cost">性能代价 (The Cost)&lt;a class="anchor" href="#%e6%80%a7%e8%83%bd%e4%bb%a3%e4%bb%b7-the-cost">#&lt;/a>&lt;/h1>
&lt;p>Cherno 给出了一针见血的职业警告：&lt;/p></description></item><item><title>72预编译头文件详解</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/72%E9%A2%84%E7%BC%96%E8%AF%91%E5%A4%B4%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3/</link><pubDate>Sun, 01 Mar 2026 12:16:57 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/72%E9%A2%84%E7%BC%96%E8%AF%91%E5%A4%B4%E6%96%87%E4%BB%B6%E8%AF%A6%E8%A7%A3/</guid><description>&lt;p>预编译头文件的作用是将大量稳定的头文件&lt;mark>提前编译成二进制缓存&lt;/mark>。这样编译器在处理每个源文件时，直接读取该缓存，而无需重新解析成千上万行重复的代码，从而极大地缩短编译时间。&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>比如常用的标准模版库：比如向量、字符串、标准输出之类，假设我们每次（在&lt;mark>每个&lt;code>.cpp&lt;/code>文件&lt;/mark>）都要包含vector，需要读取vector.h头文件并编译，而且vector本身也包含其他一系列头文件，所有其他头文件被复制到&lt;code>vector.h&lt;/code>中，再把&lt;code>vector.h&lt;/code>复制到&lt;code>.cpp&lt;/code>中（大约十万行代码），还要进行解析和标记化，并以某种形式进行编译&lt;/p>&lt;/blockquote>&lt;ul>
&lt;li>如果项目中有多个cpp文件，很多地方都包括&lt;code>vector.h&lt;/code>，他们会被逐个包含在每个文件中 &lt;del>每个翻译单元（.cpp）都会被单独编译，然后链接器将它们链接起来&lt;/del>&lt;/li>
&lt;li>且每次对那个cpp文件 &lt;del>包含了vector.h的&lt;/del> 重新更改时，整个 &lt;del>这里是说要把vector.h复制进来然后再编译&lt;/del> 都得重新编译&lt;/li>
&lt;/ul>
&lt;p>&lt;em>建议&lt;/em>&lt;/p>
&lt;ul>
&lt;li>改用预编译头文件，它会获取一堆头文件（要包含的那些），然后它编译一次，并将起转换为二进制格式。这对编译器来说处理起来比纯文件快得多 &lt;del>因为它以处于解析状态，而且是&lt;mark>二进制&lt;/mark>文件，随时可以，不用再重新编译&lt;/del>
&lt;ul>
&lt;li>举个例子，可能本来要1分钟，使用预编译头文件后，编译可能只需8秒钟&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>预编译头文件其实就是一个头文件，且包含一系列其他头文件
&lt;ul>
&lt;li>不可以把所有头文件都放进去，因为&lt;mark>如果一个头文件经常变化，那么每次改动都需要重新编译整个预编译头文件&lt;/mark>&lt;/li>
&lt;li>不需要在项目的每个cpp都包含日志文件，只需要包含含有日志的&lt;mark>预编译头文件&lt;/mark>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>C&lt;ins>库、标准模板库、WindowsAPI调用库，建议把这些都放进预编译头文件 &lt;del>每次编译可能他的代码量比实际代码还多&lt;/del> 。这样就能从每个C&lt;/ins>文件中获取所有内容，如果要用只能指针，就不用实际直接包含memory头文件，因为他在预编译头文件中，它会包含在实际编写的每个C++文件中&lt;/li>
&lt;li>因为把所有文件都放进了&lt;code>pch.h&lt;/code> &lt;del>也可以叫其他名字&lt;/del> ，所以不能一眼看出实际include了什么，且&lt;code>pch.h&lt;/code>中包含了所有的，所以也不清楚实际它&lt;mark>只依赖&lt;/mark>哪些头文件&lt;/li>
&lt;li>如果编写游戏引擎，可能只有一个cpp文件需要包含GLFW &lt;del>编译一起就搞定&lt;/del> ，那么可以把GLFW放入&lt;code>pch.h&lt;/code>中，因为其他内容都被抽象放在自己的api中；而其他的标准库、vector、标准输入输出之类的，很多都会用的，也可以让它编译一次就搞定&lt;/li>
&lt;/ul>
&lt;h1 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Main.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;pch.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello World!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//pch.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;algorithm&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;functional&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;utility&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Data structures
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;stack&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;deque&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;array&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;set&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;map&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;unordered_set&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;unordered_map&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Windows API
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;windows.h&amp;gt;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>做个测试&lt;/p>
&lt;p>&lt;img src="img/ly-20260302184649828.png" alt="" />&lt;/p>
&lt;p>然后ctrl+f7编译Main.cpp，查看生成的Main.i文件&lt;/p>
&lt;p>&lt;img src="img/ly-20260302185845788.png" alt="" />&lt;/p></description></item><item><title>71现代CPP的安全性和教学理念</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/71%E7%8E%B0%E4%BB%A3CPP%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7%E5%92%8C%E6%95%99%E5%AD%A6%E7%90%86%E5%BF%B5/</link><pubDate>Sun, 01 Mar 2026 11:37:08 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/71%E7%8E%B0%E4%BB%A3CPP%E7%9A%84%E5%AE%89%E5%85%A8%E6%80%A7%E5%92%8C%E6%95%99%E5%AD%A6%E7%90%86%E5%BF%B5/</guid><description>&lt;ul>
&lt;li>重点围绕 &lt;mark>原始指针（Raw Pointers）与智能指针（Smart Pointers）&lt;/mark> 的长期争论，以及为什么坚持从底层原理开始教学&lt;/li>
&lt;/ul>
&lt;p>视频看过一遍了，全程没有讲到代码例子，所以这里用了ai总结这个视频&lt;/p>
&lt;p>The Cherno 在本集中讨论了“安全编程”在 C++ 中的定义，重点围绕 原始指针（Raw Pointers）与智能指针（Smart Pointers） 的长期争论，以及他为什么坚持从底层原理开始教学。&lt;/p>
&lt;p>时间线总结&lt;/p>
&lt;h1 id="话题引入">话题引入&lt;a class="anchor" href="#%e8%af%9d%e9%a2%98%e5%bc%95%e5%85%a5">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>讨论 C++ 社区中关于“现代 C++”与“安全性”的激烈争论。&lt;/li>
&lt;li>两种极端观点：
&lt;ul>
&lt;li>现代派： 只应使用现代 C++，永远不碰原始指针。&lt;/li>
&lt;li>传统派： 智能指针有性能开销，真男人就该手动管理内存。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="什么是-c-中的安全性">什么是 C++ 中的“安全性”？&lt;a class="anchor" href="#%e4%bb%80%e4%b9%88%e6%98%af-c-%e4%b8%ad%e7%9a%84%e5%ae%89%e5%85%a8%e6%80%a7">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>安全编程的核心目标是：&lt;mark>减少崩溃、内存泄漏和非法访问（Access Violations）&lt;/mark>。&lt;/li>
&lt;li>从 C++11 开始，社区转向智能指针，主要是为了解决堆内存分配中的&lt;mark>人为错误&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;h1 id="内存管理的两大痛点">内存管理的两大痛点&lt;a class="anchor" href="#%e5%86%85%e5%ad%98%e7%ae%a1%e7%90%86%e7%9a%84%e4%b8%a4%e5%a4%a7%e7%97%9b%e7%82%b9">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>忘记&lt;mark>释放内存&lt;/mark>： 导致&lt;mark>内存泄漏&lt;/mark>，可能导致程序最终因内存不足而崩溃。&lt;/li>
&lt;li>&lt;mark>所有权&lt;/mark>问题（Ownership）： 当一个指针在多个函数或类之间传递时，不清楚由谁负责销毁它。&lt;/li>
&lt;/ul>
&lt;h1 id="智能指针的本质">智能指针的本质&lt;a class="anchor" href="#%e6%99%ba%e8%83%bd%e6%8c%87%e9%92%88%e7%9a%84%e6%9c%ac%e8%b4%a8">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>智能指针本质上只是对一两行代码的自动化：&lt;mark>自动调用 delete 或释放内存&lt;/mark>。&lt;/li>
&lt;li>它们通过自动化来减少人为疏忽，提高代码的健壮性。&lt;/li>
&lt;/ul>
&lt;h1 id="他的立场你应该使用智能指针">他的立场：你应该使用智能指针&lt;a class="anchor" href="#%e4%bb%96%e7%9a%84%e7%ab%8b%e5%9c%ba%e4%bd%a0%e5%ba%94%e8%af%a5%e4%bd%bf%e7%94%a8%e6%99%ba%e8%83%bd%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>在实际的生产代码或大型框架中，100% 应该&lt;mark>使用智能指针&lt;/mark>。&lt;/li>
&lt;li>不使用它们会极大地增加代码维护的难度和出错的风险。&lt;/li>
&lt;/ul>
&lt;h1 id="为什么他还在视频里用原始指针">为什么他还在视频里用原始指针？&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e4%bb%96%e8%bf%98%e5%9c%a8%e8%a7%86%e9%a2%91%e9%87%8c%e7%94%a8%e5%8e%9f%e5%a7%8b%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>简洁性： 在&lt;mark>简单&lt;/mark>的 Sandbox（沙盒）测试或只有 100 行左右的小样板代码中，原始指针写起来更快、读起来更直观。&lt;/li>
&lt;li>环境区别： 学习阶段的小程序不需要像生产环境那样严谨地考虑所有权转移。&lt;/li>
&lt;/ul>
&lt;h1 id="教学责任与影响">教学责任与影响&lt;a class="anchor" href="#%e6%95%99%e5%ad%a6%e8%b4%a3%e4%bb%bb%e4%b8%8e%e5%bd%b1%e5%93%8d">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>反思作为拥有大量订阅者的博主，&lt;mark>使用原始指针是否会给初学者带来不良示范（类似于红灯穿马路）&lt;/mark>。&lt;/li>
&lt;li>&lt;mark>但他认为，如果不教原始指针，学生就无法真正理解 C++ 的工作原理。&lt;/mark>&lt;/li>
&lt;/ul>
&lt;h1 id="核心教学哲学理解底层非常重要">核心教学哲学：理解底层（非常重要）&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e6%95%99%e5%ad%a6%e5%93%b2%e5%ad%a6%e7%90%86%e8%a7%a3%e5%ba%95%e5%b1%82%e9%9d%9e%e5%b8%b8%e9%87%8d%e8%a6%81">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>智能指针只是原始指针的封装（Wrapper）。&lt;/li>
&lt;li>如果你不&lt;mark>理解原始指针和内存是如何运作&lt;/mark>的，你就无法成为一名优秀的 C++ 程序员，尤其是处理高性能或实时系统的开发。&lt;/li>
&lt;li>==学习“旧东西”==是为了更好地掌握“新工具”。&lt;/li>
&lt;/ul>
&lt;h1 id="核心结论">核心结论&lt;a class="anchor" href="#%e6%a0%b8%e5%bf%83%e7%bb%93%e8%ae%ba">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>在项目开发中： &lt;mark>推荐使用智能指针&lt;/mark>，为了安全和效率。&lt;/li>
&lt;li>在&lt;mark>学习过程中： 必须掌握原始指针&lt;/mark>，为了理解底层和内存真相。&lt;/li>
&lt;/ul>
&lt;p>Cherno 的观点： &lt;mark>避开底层原理而只学“安全”的做法，无法培养出真正顶尖的开发者。&lt;/mark>&lt;/p></description></item><item><title>70条件断点与操作断点设置</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/70%E6%9D%A1%E4%BB%B6%E6%96%AD%E7%82%B9%E4%B8%8E%E6%93%8D%E4%BD%9C%E6%96%AD%E7%82%B9%E8%AE%BE%E7%BD%AE/</link><pubDate>Wed, 25 Feb 2026 18:43:34 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/70%E6%9D%A1%E4%BB%B6%E6%96%AD%E7%82%B9%E4%B8%8E%E6%93%8D%E4%BD%9C%E6%96%AD%E7%82%B9%E8%AE%BE%E7%BD%AE/</guid><description>&lt;ul>
&lt;li>本节介绍visual studio 快速小技巧，也是一个适用于开发和调试的通用技巧，围绕断点展开&lt;/li>
&lt;li>围绕条件展开，以及一些可应用于断点的操作
&lt;ul>
&lt;li>条件断点 &lt;del>断点在特定条件下触发&lt;/del>&lt;/li>
&lt;li>动作断点 &lt;del>断点触发时进行一些操作在控制台打印内容并继续/或暂停执行程序&lt;/del>&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;p>断点在代码里也可以实现&lt;/p>
&lt;ul>
&lt;li>写if语句并（手动）设置断点 &lt;del>也可以直接&lt;code>debug break;&lt;/code>之类的编译器内部函数&lt;/del>&lt;/li>
&lt;/ul>
&lt;p>调试中发现问题的情况下，如果使用ide的调试断点功能，就能省去重编译、编写代码再调试运行&lt;/p>
&lt;h1 id="添加action和condition">添加Action和Condition&lt;a class="anchor" href="#%e6%b7%bb%e5%8a%a0action%e5%92%8ccondition">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP70
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>, b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;i:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> i &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> b &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>先添加断点，然后再点击Action，最后添加打印内容&lt;code>i is {i} ,values of a,b is : {(float)a}, {(float)b}&lt;/code>&lt;/li>
&lt;li>然后设置Condition，设置为&lt;code>i == 3&lt;/code>，即只有在i == 3时才触发断点&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="img/ly-20260227182641735.png" alt="" />&lt;/p>
&lt;p>&lt;img src="img/ly-20260301113433709.png" alt="" />&lt;/p>
&lt;p>这个&lt;code>contine code execution&lt;/code>如果勾上了，则调试时不会停止，会直接跳过该断点&lt;/p></description></item><item><title>69类型转换</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/69%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2/</link><pubDate>Tue, 24 Feb 2026 16:59:48 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/69%E7%B1%BB%E5%9E%8B%E8%BD%AC%E6%8D%A2/</guid><description>&lt;ul>
&lt;li>类型转换（Type Casting）是在 C++ 强类型系统中进行类型间转换的过程。&lt;/li>
&lt;li>cpp作为一种强类型语言，意味着有一个类型系统，且类型是强制规定的
&lt;ul>
&lt;li>如果一个东西是整型，不能突然把它拿来当双精度数，除非有简单的==隐式转换 &lt;del>意味着cpp知道如何在这两种类型之间转换且不丢失数据&lt;/del> ==&lt;/li>
&lt;li>可以使用显示转换&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>类型转换包括&lt;mark>C风格转换&lt;/mark>和&lt;mark>C++风格转换&lt;/mark>&lt;/li>
&lt;/ul>
&lt;h1 id="基本的显示隐式转换">基本的显示/隐式转换&lt;a class="anchor" href="#%e5%9f%ba%e6%9c%ac%e7%9a%84%e6%98%be%e7%a4%ba%e9%9a%90%e5%bc%8f%e8%bd%ac%e6%8d%a2">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP69
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">double&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> a;&lt;span style="color:#75715e">//隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">double&lt;/span> value1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5.25&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a1 &lt;span style="color:#f92672">=&lt;/span> value1;&lt;span style="color:#75715e">//隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a2 &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span>)value1;&lt;span style="color:#75715e">//显示转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;a:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;value:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;value1:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5.25
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;a1:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;a2:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a2 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//成功的情况只有一种（0），而失败的原因
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//可以有成千上万种（1, 2, 3...）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="类型转换例子">类型转换例子&lt;a class="anchor" href="#%e7%b1%bb%e5%9e%8b%e8%bd%ac%e6%8d%a2%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP69
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Base&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Base() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里应该把析构函数设为vitual，我只是为了演示
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//只要有虚函数就能用动态转换转换成功，而这个虚函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不一定非得是析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#f92672">~&lt;/span>Base() {} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">virtual&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test&lt;/span>() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//public Base中 &amp;lt;public&amp;gt; 决定：基类（Base）中的成员在
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//派生类（Derived）中保持什么样的访问权限。（public则成员
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//的最高权限是public）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Derived&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Base
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Derived() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Derived() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">AnotherClass&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Base
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	AnotherClass() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>AnotherClass() {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//C风格转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5.25&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">double&lt;/span> a1 &lt;span style="color:#f92672">=&lt;/span> value &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">5.3&lt;/span>;&lt;span style="color:#75715e">//10.55
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span> a2 &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span>)value &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">5.3&lt;/span>;&lt;span style="color:#75715e">//强制截断，10.3 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span> a3 &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span>)(value &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">5.3&lt;/span>);&lt;span style="color:#75715e">//强制截断，10 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a2 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a3 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// C++风格转换（以下C风格转换都能做到，但是C++风格还会做点
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 额外的事情）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span> s &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">static_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(value) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">5.3&lt;/span>;&lt;span style="color:#75715e">//1 静态转换，会有编译时检查
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//double s1 = static_cast&amp;lt;AnotherClass&amp;gt;(value) + 5.3;//编译失败,没有哪个构造函数支持，即没有 AnotherClass(int)这样的构造函数先隐式转换成AnotherClass
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//AnotherClass s11 = static_cast&amp;lt;AnotherClass*&amp;gt;(value) ;//编译失败，无效的类型转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//AnotherClass s12 = static_cast&amp;lt;AnotherClass*&amp;gt;(&amp;amp;value) ;;//编译失败，无效的类型转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//2 重新解释转换 //类似类型双关
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	AnotherClass&lt;span style="color:#f92672">*&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">reinterpret_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>AnotherClass&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(&lt;span style="color:#f92672">&amp;amp;&lt;/span>value);&lt;span style="color:#75715e">//“重新解释转换”，编译通过，即指向该值的指针，解释成：指向另一个类实例的指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//3 动态类型转换 //多态时用到
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Derived&lt;span style="color:#f92672">*&lt;/span> derived &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Derived();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Base&lt;span style="color:#f92672">*&lt;/span> base &lt;span style="color:#f92672">=&lt;/span> derived;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//检查基类指针是否是(某个)派生类实例 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//静态转换，但很明显这会出问题(base是指向Derived实例而非AnotherClass)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	AnotherClass&lt;span style="color:#f92672">*&lt;/span> ac1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">static_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>AnotherClass&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(base);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	AnotherClass&lt;span style="color:#f92672">*&lt;/span> ac1_1 &lt;span style="color:#f92672">=&lt;/span> (AnotherClass&lt;span style="color:#f92672">*&lt;/span>)(base);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Derived&lt;span style="color:#f92672">*&lt;/span> ac3 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">dynamic_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>Derived&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(base);&lt;span style="color:#75715e">//编译通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	AnotherClass&lt;span style="color:#f92672">*&lt;/span> ac2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">dynamic_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>AnotherClass&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(base);&lt;span style="color:#75715e">//编译通过，但是返回null
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (ac3)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ac3转换成功&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//ac3转换成功
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (ac2)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ac2转换成功&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//没成功
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//4 常量解释转换：移除或添加常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//视频没说到
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//成功的情况只有一种（0），而失败的原因
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//可以有成千上万种（1, 2, 3...）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;code>dynamic_cast&lt;/code> 是在==运行时（Runtime）==通过查询虚函数表（vtable）来确认对象的实际类型的。
&lt;ul>
&lt;li>规则：只有当类中至少包含一个==虚函数（virtual function）==时，编译器才会为该类生成类型信息（RTTI）。&lt;/li>
&lt;li>所以如果&lt;mark>被转换&lt;/mark>的实例类中完全没有虚函数，那么使用&lt;code>dynamic_cast&lt;/code>时在编译阶段就报错了&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>RTTI (运行时类型识别)：当类包含虚函数时，编译器会&lt;mark>在对象内存布局中增加一个指向“虚函数表”的指针&lt;/mark>。表中包含了该类的 &lt;code>type_info&lt;/code>。&lt;/li>
&lt;li>安全性检查：执行 &lt;code>dynamic_cast&lt;/code> 时，程序会检查内存中对象的实际 &lt;code>type_info&lt;/code>。如果 &lt;code>Base* base&lt;/code> 实际上指向的是 &lt;code>Derived&lt;/code>，转换成功；如果指向的是其他不相关的类，则返回 &lt;code>NULL&lt;/code>。&lt;/li>
&lt;/ul>
&lt;h1 id="常量转换">常量转换&lt;a class="anchor" href="#%e5%b8%b8%e9%87%8f%e8%bd%ac%e6%8d%a2">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP69
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">IncreaseValue&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> val_ptr) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 编译失败：不能修改 const 指针指向的内容
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//*val_ptr = 10; 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 使用 const_cast 去掉 const 属性
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> modifiable_ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">const_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(val_ptr);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">*&lt;/span>modifiable_ptr &lt;span style="color:#f92672">+=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//number 是一个普通的非 const 变量 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> number &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;修改前: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> number &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 传入 number 的地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	IncreaseValue(&lt;span style="color:#f92672">&amp;amp;&lt;/span>number);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;修改后: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> number &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; &lt;span style="color:#75715e">// 输出 15
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//=====演示有问题情况=====
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> constant_var &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span>; &lt;span style="color:#75715e">// 原始变量就是常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>constant_var;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> naughty_ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">const_cast&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&amp;gt;&lt;/span>(ptr);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">*&lt;/span>naughty_ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">200&lt;/span>; &lt;span style="color:#75715e">// 危险！这是“未定义行为”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;constant_var修改后: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> constant_var &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 此时打印 constant_var，结果可能还是 100，也可能是 200，取决于编译器优化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>为什么number修改成功，而constant_var修改失败&lt;/p></description></item><item><title>68虚析构函数</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/68%E8%99%9A%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0/</link><pubDate>Mon, 23 Feb 2026 08:51:18 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/68%E8%99%9A%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0/</guid><description>&lt;ul>
&lt;li>虚析构函数对处理多态性而言非常重要&lt;/li>
&lt;li>如果类B从类A派生而来，&lt;code>A a=new B()&lt;/code>，现在如果决定detele a ，此时希望运行的不仅是A的析构函数，还有B的析构函数。这本质上就是虚析构函数的作用&lt;/li>
&lt;/ul>
&lt;h1 id="虚函数的核心作用与机制">虚函数的核心作用与机制&lt;a class="anchor" href="#%e8%99%9a%e5%87%bd%e6%95%b0%e7%9a%84%e6%a0%b8%e5%bf%83%e4%bd%9c%e7%94%a8%e4%b8%8e%e6%9c%ba%e5%88%b6">#&lt;/a>&lt;/h1>
&lt;p>在 C++ 中，&lt;mark>虚函数（Virtual Function）&lt;/mark> 是实现&lt;mark>多态性（Polymorphism）的核心机制&lt;/mark>。它允许程序在运行期间（Runtime）根据对象的实际类型来调用相应的函数，而不是在编译期间（Compile time）就固定死。&lt;/p>
&lt;h2 id="1-实现动态绑定-dynamic-binding">1. 实现动态绑定 (Dynamic Binding)&lt;a class="anchor" href="#1-%e5%ae%9e%e7%8e%b0%e5%8a%a8%e6%80%81%e7%bb%91%e5%ae%9a-dynamic-binding">#&lt;/a>&lt;/h2>
&lt;p>这是虚函数最直接的作用。在基类指针或引用指向派生类对象时，调用虚函数会执行“子类版本”而非“基类版本”。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>非虚函数：&lt;/mark> 编译器根据指针的&lt;mark>类型&lt;/mark>决定调用哪个函数（静态绑定）。&lt;/li>
&lt;li>&lt;mark>虚函数：&lt;/mark> 编译器根据指针指向的&lt;mark>实际对象&lt;/mark>决定调用哪个函数（动态绑定）。&lt;/li>
&lt;/ul>
&lt;h2 id="2-支持接口复用与扩展-extensibility">2. 支持接口复用与扩展 (Extensibility)&lt;a class="anchor" href="#2-%e6%94%af%e6%8c%81%e6%8e%a5%e5%8f%a3%e5%a4%8d%e7%94%a8%e4%b8%8e%e6%89%a9%e5%b1%95-extensibility">#&lt;/a>&lt;/h2>
&lt;p>通过虚函数，你可以编写通用的代码来处理不同类型的对象，而无需知道它们的具体类别。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>特性&lt;/th>
 &lt;th>说明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>&lt;mark>一致性&lt;/mark>&lt;/td>
 &lt;td>基类定义接口规范，所有子类必须遵循。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;mark>可扩展性&lt;/mark>&lt;/td>
 &lt;td>增加新的子类时，不需要修改原有的基类或调用方的逻辑。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>&lt;mark>重写 (Override)&lt;/mark>&lt;/td>
 &lt;td>子类可以根据自身需求，重新定义基类的行为。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="3-虚析构函数的重要性-virtual-destructor">3. 虚析构函数的重要性 (Virtual Destructor)&lt;a class="anchor" href="#3-%e8%99%9a%e6%9e%90%e6%9e%84%e5%87%bd%e6%95%b0%e7%9a%84%e9%87%8d%e8%a6%81%e6%80%a7-virtual-destructor">#&lt;/a>&lt;/h2>
&lt;p>在多态场景下，&lt;mark>基类的析构函数必须声明为 &lt;code>virtual&lt;/code>&lt;/mark>。&lt;/p>
&lt;ul>
&lt;li>&lt;mark>原因：&lt;/mark> 如果基类析构函数不是虚函数，当删除一个指向派生类对象的基类指针时，只会调用基类的析构函数，导致派生类特有的成员变量无法被正确释放，从而产生&lt;mark>内存泄漏 (Memory Leak)&lt;/mark>。&lt;/li>
&lt;/ul>
&lt;h2 id="4-底层实现虚函数表-vtable">4. 底层实现：虚函数表 (Vtable)&lt;a class="anchor" href="#4-%e5%ba%95%e5%b1%82%e5%ae%9e%e7%8e%b0%e8%99%9a%e5%87%bd%e6%95%b0%e8%a1%a8-vtable">#&lt;/a>&lt;/h2>
&lt;p>虚函数是通过 &lt;mark>虚函数表 (Virtual Table, vtbl)&lt;/mark> 和 &lt;mark>虚函数表指针 (vptr)&lt;/mark> 实现的：&lt;/p>
&lt;ol>
&lt;li>&lt;mark>vptr：&lt;/mark> 每个含有虚函数的对象内部都有一个隐藏指针。&lt;/li>
&lt;li>&lt;mark>vtbl：&lt;/mark> 存储了该类所有虚函数的地址。&lt;/li>
&lt;li>&lt;mark>调用过程：&lt;/mark> 程序运行阶段，通过对象的 &lt;code>vptr&lt;/code> 找到 &lt;code>vtbl&lt;/code>，再从中找到对应的函数地址。这虽然比普通函数调用稍微多了一点点开销，但换取了极大的灵活性。&lt;/li>
&lt;/ol>
&lt;h2 id="简短代码示例">简短代码示例&lt;a class="anchor" href="#%e7%ae%80%e7%9f%ad%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Animal&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">virtual&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> speak() { cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Animal speaks&amp;#34;&lt;/span>; } &lt;span style="color:#75715e">// 虚函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">virtual&lt;/span> &lt;span style="color:#f92672">~&lt;/span>Animal() {} &lt;span style="color:#75715e">// 虚析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Dog&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Animal {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> speak() &lt;span style="color:#66d9ef">override&lt;/span> { cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Woof!&amp;#34;&lt;/span>; } &lt;span style="color:#75715e">// 重写
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">makeItSpeak&lt;/span>(Animal&lt;span style="color:#f92672">*&lt;/span> a) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> a&lt;span style="color:#f92672">-&amp;gt;&lt;/span>speak(); &lt;span style="color:#75715e">// 运行阶段根据 a 指向的具体对象决定调用哪个 speak()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="类继承时构造与析构的顺序">类继承时构造与析构的顺序&lt;a class="anchor" href="#%e7%b1%bb%e7%bb%a7%e6%89%bf%e6%97%b6%e6%9e%84%e9%80%a0%e4%b8%8e%e6%9e%90%e6%9e%84%e7%9a%84%e9%a1%ba%e5%ba%8f">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP68
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Base&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Base() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Base constructor&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Base() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Base destructor&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Derived&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Base
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Derived() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Derived constructor&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Derived() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Derived destructor&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Base&lt;span style="color:#f92672">*&lt;/span> base &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Base();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span> base;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;------------------&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Derived&lt;span style="color:#f92672">*&lt;/span> derived &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Derived();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span> derived;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;------------------&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Base&lt;span style="color:#f92672">*&lt;/span> poly &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Derived();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span> poly;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">/*输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base constructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base destructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">------------------
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base constructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base destructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">------------------
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base constructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Derived constructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Derived destructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base destructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">------------------
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base constructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Derived constructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">====================&amp;gt; 输出没有这行：Derived destructor，没有调用子类析构函数，即内存泄露，没有释放m_array
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Base destructor
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>第一部分：new Base()
这是最基础的情况：&lt;/p></description></item><item><title>67联合体</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/67%E8%81%94%E5%90%88%E4%BD%93/</link><pubDate>Sat, 21 Feb 2026 09:40:10 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/67%E8%81%94%E5%90%88%E4%BD%93/</guid><description>&lt;ul>
&lt;li>联合体有点像结构体，不过一次只能占用一个成员的内存，即每个成员都共享同一块内存
&lt;ul>
&lt;li>如果我们有一个结构体，我们在里面声明四个浮点数，那就意味着我们有4个4字节，即那个结构体共有16个字节&lt;/li>
&lt;li>联合体只能有一个成员，如果声明4个浮点数(float)，如A、B、C、D，联合体的大小仍为4个字节。当尝试访问A或B或C或D时，他们实际上是同一块内存，即把A改成5，马上访问D时值也是5&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>Struct 会为每个成员分配独立空间，而 Union 里的所有成员起始地址相同。&lt;/li>
&lt;li>使用联合体的方式和使用结构体或类完全一样，也能添加静态函数、普通函数和方法 &lt;del>不能有虚方法；静态成员不占 Union 实例空间&lt;/del>&lt;/li>
&lt;li>类型双关（Type Punning）：用不同的名称或类型查看同一块原始内存。
&lt;ul>
&lt;li>当要给同一个变量取两个不同名字时，可以用联合体&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>通常联合体匿名使用、也不添加方法&lt;/li>
&lt;/ul>
&lt;h1 id="联合体不能有虚方法的原因">联合体不能有虚方法的原因&lt;a class="anchor" href="#%e8%81%94%e5%90%88%e4%bd%93%e4%b8%8d%e8%83%bd%e6%9c%89%e8%99%9a%e6%96%b9%e6%b3%95%e7%9a%84%e5%8e%9f%e5%9b%a0">#&lt;/a>&lt;/h1>
&lt;p>虚函数的工作原理依赖于虚函数表指针（vptr）。&lt;/p>
&lt;ul>
&lt;li>Class/Struct 的做法：编译器会在对象内存的开头插入一个隐藏的指针（vptr），指向该类的虚函数表（vtable）。&lt;/li>
&lt;li>Union 的冲突：Union 的所有成员都必须从偏移量 0 开始共享内存。
&lt;ul>
&lt;li>如果 Union 有虚函数，那么它必须有一个 vptr。&lt;/li>
&lt;li>这个 vptr 会占用内存。由于 Union 成员共享空间，你的数据成员（比如 int 或 float）会和这个 vptr 重叠。&lt;/li>
&lt;li>一旦你给成员赋值，就会覆盖掉 vptr，导致程序在调用虚函数时崩溃；反之，虚函数机制也会破坏你的数据。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="例子类型双关">例子：类型双关&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90%e7%b1%bb%e5%9e%8b%e5%8f%8c%e5%85%b3">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP67_
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Union&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">union&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">float&lt;/span> a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">int&lt;/span> b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Union u;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在 C++ 中，如果你在一个 struct 或 class 内部定义了一个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//_没有名字_的 union，编译器会把这个联合体的成员直接注
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//入（Injected）到外层结构体的作用域中。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	u.a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2.0f&lt;/span>;&lt;span style="color:#75715e">//0x00F6FE20 00 00 00 40
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//40 00 00 00 为 0100 0000 0000 0000 0000 0000 0000 0000
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//u.b：0表示正数，所以这个值为2^30次方，即 10,7374,1824 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//也就是我们拿到了构成那个浮点数的内存，然后把它当做int来解释(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//类型双关）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> u.a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> u.b &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="相对拙劣的做法">相对拙劣的做法&lt;a class="anchor" href="#%e7%9b%b8%e5%af%b9%e6%8b%99%e5%8a%a3%e7%9a%84%e5%81%9a%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP67
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y, z, w;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetA()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//把&amp;amp;x当成一个Vector2的地址来解释
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//*表示取值的时候连续取两个float的值来构成一个Vector2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>(Vector2&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">&amp;amp;&lt;/span>x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//尝试把Vector4看成是两个Vector2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Vector2 GetA()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//..
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	//添加一些成员并返回，这里省略了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	return Vector2();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintVector2&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> v)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Vector2: (&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;)&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="利用union原理并巧妙使用它">利用union原理并巧妙使用它&lt;a class="anchor" href="#%e5%88%a9%e7%94%a8union%e5%8e%9f%e7%90%86%e5%b9%b6%e5%b7%a7%e5%a6%99%e4%bd%bf%e7%94%a8%e5%ae%83">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP67
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//最外层 struct Vector4：定义了这块内
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 存的总大小（4 x 4 = 16 字节）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector4&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个“平行空间”。它(union)告诉编译器：“我内部定义的所有东西，都从同一个起始地址开始存放”。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">union&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//union的大小，是它内部最大的成员的大小。在这个例子中，union的大小是16字节（4个float，每个4字节）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//它把这 16 字节切分成了四个 float
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//，并分别取名为 x, y, z, w。(这个struct
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//是联合体的第1个成员）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">struct&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">float&lt;/span> x, y, z, w;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//(这个struct是联合体的第2个成员）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">struct&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			Vector2 a, b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintVector2&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> v)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Vector2: (&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v.y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;)&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector4 vector &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">1.0f&lt;/span>, &lt;span style="color:#ae81ff">2.0f&lt;/span>, &lt;span style="color:#ae81ff">3.0f&lt;/span>, &lt;span style="color:#ae81ff">4.0f&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//可以用vector.x,vector.y,vector.z,vector.w来访问这四个float
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//或者用vector.a和vector.b来访问这两个Vector2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//且vector.a.x和vector.a.y分别对应vector.x和vector.y，vector.b.x和vector.b.y分别对应vector.z和vector.w(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//因为它们共享同一块内存，所以修改其中一个成员会影响到其他成员的值)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vector.x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Vector4: (&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vector.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vector.y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vector.z &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;, &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vector.w &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;)&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;&lt;span style="color:#75715e">// Vector4: (2, 2, 3, 4)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//验证上述结论
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//这里修改了z却间接修改了vector.b
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vector.z &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">500.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;-----&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintVector2(vector.a); &lt;span style="color:#75715e">// Vector2: (2, 2)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	PrintVector2(vector.b); &lt;span style="color:#75715e">// Vector2: (500, 4)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>66类型双关</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/66%E7%B1%BB%E5%9E%8B%E5%8F%8C%E5%85%B3/</link><pubDate>Tue, 17 Feb 2026 08:59:40 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/66%E7%B1%BB%E5%9E%8B%E5%8F%8C%E5%85%B3/</guid><description>&lt;ul>
&lt;li>类型双关指的是，C&lt;ins>绕过类型系统的一种方式，C&lt;/ins>是强类型语言，不会把所有东西都设置为auto（可以，但不推荐）&lt;/li>
&lt;li>C++中类型在一定程度上&lt;mark>由编译器强制限定&lt;/mark>，但你可以&lt;mark>直接访问内存&lt;/mark>&lt;/li>
&lt;li>本章节实例会访问某个int数值的内存，并把它当做双精度数来处理（轻易绕过类型系统）
&lt;ul>
&lt;li>假设有一个类（基本类型结构体），我们想把它写成字节流，它没有其他指针指向它，那么我们可以直接解释整个结构体、类、或者其他东西，这里会视为字节数组：只要我们知道任何大小，就可以直接访问数据&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;h1 id="转换">转换&lt;a class="anchor" href="#%e8%bd%ac%e6%8d%a2">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP66
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//小端法，低字节的数据存储在内存的低地址处，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 高字节的数据存储在内存的高地址处
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Ox00000032
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>;&lt;span style="color:#75715e">// 32 00 00 00 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式转换，a隐式转换成了double类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//相当于 double value =(double)a
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Ox404900000000000000，double数值50
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//的16进制表示为0x4049000000000000
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> a;&lt;span style="color:#75715e">// 00 00 00 00 00 00 49 40 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;mark>转换后内存中的数值变了&lt;/mark>&lt;/p>
&lt;h1 id="类型双关-不同方式读取同一内存">类型双关-不同方式读取同一内存&lt;a class="anchor" href="#%e7%b1%bb%e5%9e%8b%e5%8f%8c%e5%85%b3-%e4%b8%8d%e5%90%8c%e6%96%b9%e5%bc%8f%e8%af%bb%e5%8f%96%e5%90%8c%e4%b8%80%e5%86%85%e5%ad%98">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP66
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//把a(内存处）的内存以double类型的方式进行访问
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//将整型进行类型双关变成双精度型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//* 操作符会尝试从该地址开始，一口气往后读 8 个字节，这里是
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//32 00 00 00 cc cc cc cc （小端法）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#66d9ef">double&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">&amp;amp;&lt;/span>a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不想创建全新变量，只是想把这个整数当成双精度数来访问，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//那么可以在这个双精度数后面加&amp;amp;，这样就能引用他
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//强行让 value1 成为 &amp;amp;a 处那块 8 字节内存的别名。通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// value1 修改数据会直接破坏 a 及其相邻内存。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">double&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#66d9ef">double&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">&amp;amp;&lt;/span>a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里会把8个字节(a和a后面的4个字节)都写入0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	value1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="img/ly-20260220131817492.png" alt="" />&lt;/p></description></item><item><title>65排序</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/65%E6%8E%92%E5%BA%8F/</link><pubDate>Mon, 16 Feb 2026 23:31:44 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/65%E6%8E%92%E5%BA%8F/</guid><description>&lt;ul>
&lt;li>数据结构决定了数据的存储方式&lt;/li>
&lt;li>本节主要讲解如何对现有数据进行排序&lt;/li>
&lt;li>当使用C&lt;ins>及其内置集合类型,如&lt;code>std::vector&lt;/code>时,优先用C&lt;/ins>内置的函数排序:能根据你&lt;mark>提供的任何迭代器&lt;/mark>进行&lt;mark>实际排序&lt;/mark>&lt;/li>
&lt;/ul>
&lt;h1 id="cppreference中的解释">cppreference中的解释&lt;a class="anchor" href="#cppreference%e4%b8%ad%e7%9a%84%e8%a7%a3%e9%87%8a">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//std::sort
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Defined in header &amp;lt;algorithm&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">RandomIt&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> sort( RandomIt first, RandomIt last ); (&lt;span style="color:#ae81ff">1&lt;/span>)(&lt;span style="color:#66d9ef">constexpr&lt;/span> since C&lt;span style="color:#f92672">++&lt;/span>&lt;span style="color:#ae81ff">20&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ExecutionPolicy&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">RandomIt&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> sort( ExecutionPolicy&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> policy,
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> RandomIt first, RandomIt last ); (&lt;span style="color:#ae81ff">2&lt;/span>)(since C&lt;span style="color:#f92672">++&lt;/span>&lt;span style="color:#ae81ff">17&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">RandomIt&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Compare&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> sort( RandomIt first, RandomIt last, Compare comp ); (&lt;span style="color:#ae81ff">3&lt;/span>)(&lt;span style="color:#66d9ef">constexpr&lt;/span> since C&lt;span style="color:#f92672">++&lt;/span>&lt;span style="color:#ae81ff">20&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ExecutionPolicy&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">RandomIt&lt;/span>, &lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Compare&lt;/span> &lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> sort( ExecutionPolicy&lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> policy, RandomIt first, RandomIt last, Compare comp ); (&lt;span style="color:#ae81ff">4&lt;/span>)(since C&lt;span style="color:#f92672">++&lt;/span>&lt;span style="color:#ae81ff">17&lt;/span>)&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>可以传入迭代器、谓词（非必须）&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>迭代器：&lt;mark>存储了原数据的地址&lt;/mark>。可以利用迭代器迭代原数据，存储了地址所以可以方便的交换数据&lt;/p>&lt;/blockquote>&lt;p>没有返回值，时间复杂度为&lt;code>O(N·log(N))&lt;/code>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>Given N as last &lt;span style="color:#f92672">-&lt;/span> first:
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>) O(N&lt;span style="color:#960050;background-color:#1e0010">·&lt;/span>log(N)) comparisons &lt;span style="color:#66d9ef">using&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>(until C&lt;span style="color:#f92672">++&lt;/span>&lt;span style="color:#ae81ff">20&lt;/span>)std&lt;span style="color:#f92672">::&lt;/span>less{}(since C&lt;span style="color:#f92672">++&lt;/span>&lt;span style="color:#ae81ff">20&lt;/span>).
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#ae81ff">3&lt;/span>,&lt;span style="color:#ae81ff">4&lt;/span>) O(N&lt;span style="color:#960050;background-color:#1e0010">·&lt;/span>log(N)) applications of the comparator comp.&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;p>algorithm：&lt;code>英[ˈælɡərɪðəm]&lt;/code>&lt;/p></description></item><item><title>64多维数组</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/64%E5%A4%9A%E7%BB%B4%E6%95%B0%E7%BB%84/</link><pubDate>Sat, 14 Feb 2026 11:22:55 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/64%E5%A4%9A%E7%BB%B4%E6%95%B0%E7%BB%84/</guid><description>&lt;ul>
&lt;li>多维数组,其实就是由数组作为元素,构成的数组&lt;/li>
&lt;/ul>
&lt;h1 id="二维数组与三维数组">二维数组与三维数组&lt;a class="anchor" href="#%e4%ba%8c%e7%bb%b4%e6%95%b0%e7%bb%84%e4%b8%8e%e4%b8%89%e7%bb%b4%e6%95%b0%e7%bb%84">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//存储50个整数, 指针存储这50个整数的第一个数的地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//50*4=200字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> array &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//A2D, 2D数组,50个[整数指针]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//分配50个[整数指针]; 32位系统，一个指针4字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//50*4=200字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">**&lt;/span> a2d &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//都是分配了200个字节,4个字节一组,总共50组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//类型,其实就是在设置处理这些属性的语法,比如 int* array,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//int** a2d等等
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	array[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;&lt;span style="color:#75715e">//处理的是整数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	a2d[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;&lt;span style="color:#75715e">//处理的是指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//有空间存储50个指针,这些指针共占200字节,之后我们可以遍历
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//它们,并将每个指针都设置为指向一个数组. 其实最终得到的就是50个数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//二维数组: 有一个数组,包含着(50个)[数组的内存地址] 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//为50个数组元素(指针)处理操作
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//让每一个数组元素(指针)的值,等于new(50个元素)出来的数组的首地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		a2d[i] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//分配50个(二维数组)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">***&lt;/span> a3d &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">**&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//遍历每一个二维数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//初始化二维数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		a3d[i] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> [&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//遍历a3d[i]这个数组的50个元素
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> j &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; j &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>; j&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">**&lt;/span> ptr &lt;span style="color:#f92672">=&lt;/span> a3d[i];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//让每个元素指向new出的50个元素的数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			ptr[j] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//a3d[0]:得到一个二级指针数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//a3d[0][0]:得到一个指针数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//a3d[0][0][0]:得到整数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	a3d[&lt;span style="color:#ae81ff">0&lt;/span>][&lt;span style="color:#ae81ff">0&lt;/span>][&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="详解二维数组">详解二维数组&lt;a class="anchor" href="#%e8%af%a6%e8%a7%a3%e4%ba%8c%e7%bb%b4%e6%95%b0%e7%bb%84">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP64
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建一个数组,每个数组元素是指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">**&lt;/span> a2d &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> [&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//对50个元素赋值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//对第i个指针元素赋值,每个指针元素
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//指向新创建的数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		a2d[i] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//第1个数组的第一个元素赋值为0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//左边的0是指针的索引
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//右边的0,1,2是整数的索引
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	a2d[&lt;span style="color:#ae81ff">0&lt;/span>][&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	a2d[&lt;span style="color:#ae81ff">0&lt;/span>][&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	a2d[&lt;span style="color:#ae81ff">0&lt;/span>][&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//没有这种语法,编译报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//delete[][] a2d;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">50&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//删除所有内部的数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] a2d[i];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这个删除的是,保存指针元素的那个数组(最外层)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">delete&lt;/span>[] a2d;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="内存碎片化">内存碎片化&lt;a class="anchor" href="#%e5%86%85%e5%ad%98%e7%a2%8e%e7%89%87%e5%8c%96">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP64
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//包含5个指针元素的数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">**&lt;/span> a2d &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> [&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//每个元素都包含五个数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		a2d[i] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//设置元素的值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; y &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; y&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; x &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; x&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			a2d[y][x] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这25个元素并不是一个连续的能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//容纳25个整数的缓冲区,而是5个独立
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//的缓冲区,每个缓冲区能容纳5个整数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//这5个缓冲区,被分配到内存中的随机位置
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//删除所有内部的数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">delete&lt;/span>[] a2d[i];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这个删除的是,保存指针元素的那个数组(最外层)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">delete&lt;/span>[] a2d;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>如果我们必须遍历,&lt;mark>每次遍历5个整数后(访问25个整数中的每一组),然后转到数组的下一行(下一个整数数组)&lt;/mark>,到内存中的另一个位置&lt;mark>读取/写入&lt;/mark>数据,这可能会导致缓存未命中,这意味着从内存中获取数据时会浪费时间(如果他们分配得很近可能不会缓存未命中)
&lt;ul>
&lt;li>如上所示,这样遍历这25个整数,比&lt;mark>在内存中连续分配一个25个&lt;/mark>整数的一维数组慢很多,因为那段内存是连续的&lt;/li>
&lt;li>当你编程优化时,当你处理内存时,&lt;mark>优化时最重要的一件事就是优化内存访问&lt;/mark>&lt;/li>
&lt;li>如果能够&lt;mark>在内存中紧凑存储要访问的内存&lt;/mark>,并且通过某种方式摆放,以获得更多的缓存命中,使程序运行更快&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>缓存学习包括:CPU缓存如何工作&lt;/li>
&lt;/ul>
&lt;h1 id="代替二维数组">代替二维数组&lt;a class="anchor" href="#%e4%bb%a3%e6%9b%bf%e4%ba%8c%e7%bb%b4%e6%95%b0%e7%bb%84">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP64
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这是一个栈上的原生二维数组,且内存中连续(对比int** a2d = new int* [5];方式)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//物理形态：[ 1, 2, 3, 4, 5, 6, 7, ... 25 ] 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//特点：编译器通过公式 Address + (row x 5 + col) x 4 直接定位。没有额外的寻址操作。(字节定位)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> a[&lt;span style="color:#ae81ff">5&lt;/span>][&lt;span style="color:#ae81ff">5&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span>,&lt;span style="color:#ae81ff">4&lt;/span>,&lt;span style="color:#ae81ff">5&lt;/span>,&lt;span style="color:#ae81ff">6&lt;/span>,&lt;span style="color:#ae81ff">7&lt;/span>,&lt;span style="color:#ae81ff">8&lt;/span>,&lt;span style="color:#ae81ff">9&lt;/span>,&lt;span style="color:#ae81ff">10&lt;/span>, &lt;span style="color:#ae81ff">11&lt;/span>,&lt;span style="color:#ae81ff">12&lt;/span>,&lt;span style="color:#ae81ff">13&lt;/span>,&lt;span style="color:#ae81ff">14&lt;/span>,&lt;span style="color:#ae81ff">15&lt;/span>,&lt;span style="color:#ae81ff">16&lt;/span>,&lt;span style="color:#ae81ff">17&lt;/span>,&lt;span style="color:#ae81ff">18&lt;/span>,&lt;span style="color:#ae81ff">19&lt;/span>,&lt;span style="color:#ae81ff">20&lt;/span>, &lt;span style="color:#ae81ff">21&lt;/span>, &lt;span style="color:#ae81ff">22&lt;/span>, &lt;span style="color:#ae81ff">23&lt;/span>, &lt;span style="color:#ae81ff">24&lt;/span>, &lt;span style="color:#ae81ff">25&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> j &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; j &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; j&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a[i][j] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//使用一维数组(连续的一块内存)完成二维数组5 * 5 的数组功能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> array &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; y &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; y&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; x &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; x&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			array[x &lt;span style="color:#f92672">+&lt;/span> y &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="建议">建议&lt;a class="anchor" href="#%e5%bb%ba%e8%ae%ae">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>避免使用二维数组,如果存储一个位图,有一幅图像的所有元素,会把图像(正方形或长方形)看成二维的,但不代表要把它存为二维数组,建议存为一维数组&lt;/li>
&lt;/ul>
&lt;h2 id="为什么推荐平铺的一维数组而不是int-a55">为什么推荐“平铺的一维数组”而不是&lt;code>int a[5][5]&lt;/code>？&lt;a class="anchor" href="#%e4%b8%ba%e4%bb%80%e4%b9%88%e6%8e%a8%e8%8d%90%e5%b9%b3%e9%93%ba%e7%9a%84%e4%b8%80%e7%bb%b4%e6%95%b0%e7%bb%84%e8%80%8c%e4%b8%8d%e6%98%afint-a55">#&lt;/a>&lt;/h2>
&lt;ul>
&lt;li>动态需求：实际开发中（如加载一张图片），你往往在运行时才知道宽度和高度。这时你无法使用 &lt;code>int a[W][H]&lt;/code> (W和H如果是动态则编译失败)，只能用 &lt;code>new&lt;/code>。&lt;/li>
&lt;li>统一性：如果你习惯了 &lt;code>array[y * width + x]&lt;/code>，那么无论数组是在栈上(&lt;code>int array[25];&lt;/code>)还是堆上(&lt;code>int* array = new int[width * height];&lt;/code>)，你的&lt;mark>逻辑&lt;/mark> &lt;del>底层逻辑&lt;/del> 都是统一的。
&lt;ul>
&lt;li>对比：如果你用原生语法，栈上是 &lt;code>a[y][x]&lt;/code>，堆上如果你用 &lt;code>int**&lt;/code> 也是 &lt;code>a[y][x]&lt;/code> &lt;del>如果用&lt;code>int* array = new int[width * height];&lt;/code>就没办法用这种形式. 和前者甚至不🙆‍♀️&lt;/del> ，但它们的&lt;mark>底层指令完全不同（一个计算偏移，一个跳转指针）&lt;/mark>，且不能互相传递。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>传递方便：将 &lt;code>int a[5][5]&lt;/code> 作为参数传递给函数很麻烦（必须指定列数，如 &lt;code>void func(int arr[][5])&lt;/code>），而传递一个 &lt;code>int*&lt;/code> 则非常&lt;mark>简单通用&lt;/mark>。
&lt;ul>
&lt;li>&lt;mark>编译器&lt;/mark>必须知道“每一行有多少个元素”，否则它无法计算出&lt;code>a[i][j]&lt;/code>的内存地址。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul></description></item><item><title>63计时</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/63%E8%AE%A1%E6%97%B6/</link><pubDate>Thu, 12 Feb 2026 19:39:48 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/63%E8%AE%A1%E6%97%B6/</guid><description>&lt;ul>
&lt;li>计时：完成某项操作或执行特定代码所需的时间&lt;/li>
&lt;li>c++17加入了 chrono&lt;/li>
&lt;/ul>
&lt;h1 id="计时简单例子">计时简单例子&lt;a class="anchor" href="#%e8%ae%a1%e6%97%b6%e7%ae%80%e5%8d%95%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP63
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//引入了本节所需要的大部分内容
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//跨平台计时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//线程相关
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//为了使用1s表示1秒的用法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> &lt;span style="color:#66d9ef">namespace&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>literals&lt;span style="color:#f92672">::&lt;/span>chrono_literals;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//获取当前时间
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//auto--&amp;gt; std::chrono::steady_clock::time_point
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> start &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">::&lt;/span>now();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//模拟耗时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//指定大概睡眠1秒，会有其他开销
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>this_thread&lt;span style="color:#f92672">::&lt;/span>sleep_for(&lt;span style="color:#ae81ff">1&lt;/span>s);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">auto&lt;/span> end &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">::&lt;/span>now();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//算出实际时长
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//也可以用auto
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>duration&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">float&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> duration &lt;span style="color:#f92672">=&lt;/span> end &lt;span style="color:#f92672">-&lt;/span> start;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> duration.count() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;s&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif &lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="解释字面量1s">解释字面量&lt;code>1s&lt;/code>&lt;a class="anchor" href="#%e8%a7%a3%e9%87%8a%e5%ad%97%e9%9d%a2%e9%87%8f1s">#&lt;/a>&lt;/h2>
&lt;p>&lt;code>1s&lt;/code> 被称为 &lt;mark>用户定义字面量 (User-defined literals)&lt;/mark>，代表一个 &lt;code>std::chrono::seconds&lt;/code> 对象，其值为 1。字面量本质上是调用了一个特殊的运算符函数&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 编译器实际执行的操作（示意）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>s(&lt;span style="color:#ae81ff">1&lt;/span>);&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在c++的标准库的头文件中，它的定义大致如下：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 简化后的底层实现
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">constexpr&lt;/span> chrono&lt;span style="color:#f92672">::&lt;/span>seconds &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>s(&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">long&lt;/span> &lt;span style="color:#66d9ef">long&lt;/span> _Val) &lt;span style="color:#66d9ef">noexcept&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> chrono&lt;span style="color:#f92672">::&lt;/span>seconds(_Val);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>&lt;mark>operator&amp;quot;&amp;quot;：这是定义字面量的关键字&lt;/mark>。&lt;/li>
&lt;li>s：这是后缀名称。&lt;/li>
&lt;li>constexpr：意味着这个转换在编译期就能完成，没有任何运行时开销（Runtime overhead）。&lt;/li>
&lt;/ul>
&lt;h1 id="给函数计时">给函数计时&lt;a class="anchor" href="#%e7%bb%99%e5%87%bd%e6%95%b0%e8%ae%a1%e6%97%b6">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP63
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//引入了本节所需要的大部分内容
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//跨平台计时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">//线程相关
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Timer&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>time_point&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>steady_clock&lt;span style="color:#f92672">&amp;gt;&lt;/span> start, end;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>duration&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">float&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> duration;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Timer()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		start &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">::&lt;/span>now();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Timer()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		end &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>chrono&lt;span style="color:#f92672">::&lt;/span>high_resolution_clock&lt;span style="color:#f92672">::&lt;/span>now();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		duration &lt;span style="color:#f92672">=&lt;/span> end &lt;span style="color:#f92672">-&lt;/span> start;&lt;span style="color:#75715e">//可以省略不存储结束值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//1000.0f不是重载，而是编译器硬编码的，1000f会编译报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">float&lt;/span> ms &lt;span style="color:#f92672">=&lt;/span> duration.count() &lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#ae81ff">1000.0f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//24ms
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//std::cout &amp;lt;&amp;lt; &amp;#34;Timer took &amp;#34; &amp;lt;&amp;lt; ms &amp;lt;&amp;lt; &amp;#34;ms&amp;#34; &amp;lt;&amp;lt; std:: endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//21ms
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Timer took &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> ms &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;ms&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>;&lt;span style="color:#75715e">// &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Function&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//作用域(函数)内创建Timer对象,整个(函数)作用域(结束后)都会被计时
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Timer timer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Function();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif &lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="其他">其他&lt;a class="anchor" href="#%e5%85%b6%e4%bb%96">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>visual studio也自带分析工具&lt;/li>
&lt;li>或者其他任何集成开发环境也许自带分析工具&lt;/li>
&lt;li>可以在源代码中修改使其具有类似的计时(分析)工具&lt;/li>
&lt;li>还可以用来展示每个函数运行时长的图表,以及那个函数调用了哪个函数&lt;/li>
&lt;/ul></description></item><item><title>62多线程</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/62%E5%A4%9A%E7%BA%BF%E7%A8%8B/</link><pubDate>Thu, 12 Feb 2026 16:16:06 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/62%E5%A4%9A%E7%BA%BF%E7%A8%8B/</guid><description>&lt;ul>
&lt;li>&lt;code>std::cin.get()&lt;/code> &lt;em>等待用户输入的那段时间&lt;/em>，什么也做不了。此时就可以在后台开另一个线程做其他事&lt;/li>
&lt;/ul>
&lt;p>从这篇开始，代码都会写在同一个项目中，使用&lt;code>Mainxx_yy.cpp&lt;/code>的类似名字。由于同一个项目有多个main函数（同一篇都好几个），所以文件最顶端添加宏进行判断，visual studio中对项目配置如下&lt;br>
&lt;img src="img/ly-20260212193719758.png" alt="" />&lt;/p>
&lt;h1 id="函数声明与类创建区别">函数声明与类创建&lt;code>[区别]&lt;/code>&lt;a class="anchor" href="#%e5%87%bd%e6%95%b0%e5%a3%b0%e6%98%8e%e4%b8%8e%e7%b1%bb%e5%88%9b%e5%bb%ba%e5%8c%ba%e5%88%ab">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP62
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Test()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Test()&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Test(&lt;span style="color:#66d9ef">int&lt;/span> k)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Test(int)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">DoWork&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//声明一个类Test的对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Test t{};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 这是一个函数声明，声明一个函数名
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 为 t1，没有参数，返回类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 是 Test
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Test t1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 这是一个函数声明，声明一个函数名
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 为 worker，没有参数，返回类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 是 int
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//声明一个线程对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker2{};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建线程并立即启动DoWork内的操作
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker(DoWork);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	worker.join();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="线程简单例子">线程简单例子&lt;a class="anchor" href="#%e7%ba%bf%e7%a8%8b%e7%ae%80%e5%8d%95%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP62
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">DoWork&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 这是一个函数声明，声明一个函数名
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 为 worker，没有参数，返回类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 是 int
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建的是一个“空”线程对象，内部没有关联
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 任何实际的执行函数，也不启动线程
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker2{};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//创建线程并立即启动DoWork内的操作
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker(DoWork);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//...启动-&amp;gt;到join这期间的代码并
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不会阻塞
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//主线程会等待
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//主线程会停在 join() 这一行，像在车站等
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 朋友一样，直到子线程这辆车“到站”并合
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 二为一，主线程才会继续往下走。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	worker.join();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//子线程完成前不会执行该行代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>join的作用：让当前线程（通常是主线程）停下来，进入阻塞状态，直到子线程执行完毕为止。&lt;/li>
&lt;li>主线程启动一个工作线程，工作线程执行任务，然后在主线程上等待工作线程完成所有任务&lt;/li>
&lt;/ul>
&lt;h1 id="子线程无限循环">子线程无限循环&lt;a class="anchor" href="#%e5%ad%90%e7%ba%bf%e7%a8%8b%e6%97%a0%e9%99%90%e5%be%aa%e7%8e%af">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP62
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">DoWork&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">while&lt;/span> (true)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;working...&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker(DoWork); 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	worker.join();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//子线程完成前不会执行该行代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="阻止无限循环">阻止无限循环&lt;a class="anchor" href="#%e9%98%bb%e6%ad%a2%e6%97%a0%e9%99%90%e5%be%aa%e7%8e%af">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP62
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;thread&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 显式包含时间库
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//cherno视频里没有却能运行，可能是有些编译器中，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// &amp;lt;thread&amp;gt; 头文件为了实现 sleep_for 等功能，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 其内部已经写了 #include &amp;lt;chrono&amp;gt;。(ai回答)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;chrono&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">bool&lt;/span> s_Finished &lt;span style="color:#f92672">=&lt;/span> false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">DoWork&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">using&lt;/span> &lt;span style="color:#66d9ef">namespace&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>literals&lt;span style="color:#f92672">::&lt;/span>chrono_literals;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">while&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>s_Finished)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;working...&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>this_thread&lt;span style="color:#f92672">::&lt;/span>sleep_for(&lt;span style="color:#ae81ff">1&lt;/span>s);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">thread&lt;/span> worker(DoWork);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//主线程自己阻塞自己了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//用户按下回车后
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	s_Finished&lt;span style="color:#f92672">=&lt;/span>true;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//按下回车后，子线程或许刚进入
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//while语句块{ ，且还没到达打印语句
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//所以可能子线程要再打印一行，之后下
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//一次循环才不会进入
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	worker.join();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;===child thread finished~~==&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//子线程完成前不会执行该行代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">/* 输出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">working...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">working...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">working...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">working...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">working...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">		 //这就是用户按下的回车行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">working...
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">===child thread over~==
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>子线程配合join可以用来做&lt;mark>清理&lt;/mark>工作，主线程等待子线程清理完毕后再退出或执行某些操作&lt;/p></description></item><item><title>61(60)避免使用命名空间</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/6160%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A8%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/</link><pubDate>Thu, 12 Feb 2026 10:14:23 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/6160%E9%81%BF%E5%85%8D%E4%BD%BF%E7%94%A8%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/</guid><description>&lt;h1 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20260212105908628.png" alt="" />&lt;/p>
&lt;p>代码简化&lt;/p>
&lt;p>&lt;img src="img/ly-20260212105939698.png" alt="" />&lt;/p>
&lt;p>也可以只在函数内部（或者其他作用域）声明&lt;/p>
&lt;p>&lt;img src="img/ly-20260212110006704.png" alt="" />&lt;/p>
&lt;p>但是有个缺点，没法直接判断vector是哪来的，&lt;mark>标准的？还是自己写的&lt;/mark>。&lt;/p>
&lt;h1 id="代码示例">代码示例&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e7%a4%ba%e4%be%8b">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> apple {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> text &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> orange {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>string temp &lt;span style="color:#f92672">=&lt;/span> text;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>reverse(temp.begin(), temp.end());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> temp &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">using&lt;/span> &lt;span style="color:#66d9ef">namespace&lt;/span> apple;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">using&lt;/span> &lt;span style="color:#66d9ef">namespace&lt;/span> orange;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//:: 这个是作用域解析运算符 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	apple&lt;span style="color:#f92672">::&lt;/span>print(&lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//寻找更为匹配的 orange::print
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	print(&lt;span style="color:#e6db74">&amp;#34;hello&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Hello
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">olleh
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="建议">建议&lt;a class="anchor" href="#%e5%bb%ba%e8%ae%ae">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>任何时候都不要在头文件(xx.h)里面放入&lt;code>using namespace xx;&lt;/code>，因为没人知道它会被include到哪里&lt;/li>
&lt;li>尽量只有自己的库才用它&lt;/li>
&lt;li>尽量在更小的作用域内使用 &lt;del>if、函数、最多是在文件&lt;/del>&lt;/li>
&lt;/ul></description></item><item><title>60(61)命名空间</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/6061%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/</link><pubDate>Wed, 11 Feb 2026 23:43:16 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/6061%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/</guid><description>&lt;ul>
&lt;li>命名空间是什么、有什么用、何时使用、何时不使用、他们有什么用&lt;/li>
&lt;li>主要用途是避免命名冲突&lt;/li>
&lt;/ul>
&lt;h1 id="6061命名空间">60(61)命名空间&lt;a class="anchor" href="#6061%e5%91%bd%e5%90%8d%e7%a9%ba%e9%97%b4">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> apple {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> text &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> orange {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>string temp &lt;span style="color:#f92672">=&lt;/span> text;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>reverse(temp.begin(), temp.end());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> text &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//:: 这个是作用域解析运算符 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	apple&lt;span style="color:#f92672">::&lt;/span>print(&lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果这段代码没有命名空间，那么就存在两个函数签名一模一样的函数，编译都过不去 &lt;del>两个同名且相同的符号（类，函数，变量，常量），同一文件中会编译错误，不同文件则链接错误&lt;/del>&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>C语言没有命名空间语法，所以比如glfw库中的函数都是以glfw开头（避免冲突）&lt;/p>&lt;/blockquote>&lt;h2 id="如果没有命名空间">如果没有命名空间&lt;a class="anchor" href="#%e5%a6%82%e6%9e%9c%e6%b2%a1%e6%9c%89%e5%91%bd%e5%90%8d%e7%a9%ba%e9%97%b4">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//namespace apple {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">apple_print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> text &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//namespace orange {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">orange_print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>string temp &lt;span style="color:#f92672">=&lt;/span> text;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>reverse(temp.begin(), temp.end());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> text &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	apple_print(&lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="代码编写风格">代码编写风格&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e7%bc%96%e5%86%99%e9%a3%8e%e6%a0%bc">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> apple { &lt;span style="color:#66d9ef">namespace&lt;/span> functions {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> text)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> text &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这么做仅仅是为了减少缩进&lt;/p></description></item><item><title>58_59函数指针、lambda表达式</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/58_59%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/</link><pubDate>Tue, 10 Feb 2026 23:42:53 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/58_59%E5%87%BD%E6%95%B0%E6%8C%87%E9%92%88lambda%E8%A1%A8%E8%BE%BE%E5%BC%8F/</guid><description>&lt;p>本篇聊聊&lt;mark>来自C语言的那种原始风格函数指针&lt;/mark>，后续会讲C++处理函数指针的方法，以及lambda表达式&lt;/p>
&lt;ul>
&lt;li>函数指针，是一种把&lt;mark>函数赋给变量&lt;/mark>的方式&lt;/li>
&lt;li>函数只是个符号，并不能进行任何逻辑计算，但是可以拿来调用&lt;/li>
&lt;li>可以接受传参，如果返回非void可以得到相应结果&lt;/li>
&lt;li>函数可以赋值给变量，函数也可以作为参数传递给其他函数&lt;/li>
&lt;li>函数是cpu指令，存储在我们的二进制文件中的某处&lt;/li>
&lt;li>&lt;code>auto function = HelloWorld;&lt;/code>，获取cpu指令的内存地址并赋值给function&lt;/li>
&lt;/ul>
&lt;h1 id="58_59函数指针lambda表达式">58_59函数指针、lambda表达式&lt;a class="anchor" href="#58_59%e5%87%bd%e6%95%b0%e6%8c%87%e9%92%88lambda%e8%a1%a8%e8%be%be%e5%bc%8f">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">HelloWorld&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;HelloWorld!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//function的类型-&amp;gt;void (*function)()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> function1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>HelloWorld;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//&amp;amp;可以省略，因为有隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> function &lt;span style="color:#f92672">=&lt;/span> HelloWorld;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//相当于
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> (&lt;span style="color:#f92672">*&lt;/span>function2)() &lt;span style="color:#f92672">=&lt;/span> HelloWorld;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	function();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	(&lt;span style="color:#f92672">*&lt;/span>function)();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	function1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	(&lt;span style="color:#f92672">*&lt;/span>function1)();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	function2();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	(&lt;span style="color:#f92672">*&lt;/span>function2)();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="隐式转换">隐式转换&lt;a class="anchor" href="#%e9%9a%90%e5%bc%8f%e8%bd%ac%e6%8d%a2">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>为什么不需要 &amp;amp;？
当你直接使用函数名 HelloWorld 时，编译器会将其视为该函数在内存中的起始地址。&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>auto function = HelloWorld;：编译器看到函数名，自动将其转换为函数指针。&lt;/li>
&lt;li>auto function = &amp;amp;HelloWorld;：显式地取函数地址。&lt;/li>
&lt;/ul>
&lt;p>这两行代码生成的机器码通常是完全一样的。&lt;/p>
&lt;ol start="2">
&lt;li>只有一种情况“必须”注意
虽然对于普通函数两者等价，但在处理类成员函数 (Member Functions) 时，规则会变严：&lt;/li>
&lt;/ol>
&lt;ul>
&lt;li>普通函数： &amp;amp; 可选。&lt;/li>
&lt;li>类成员函数： 必须使用 &amp;amp; 并且加上类名限定。&lt;/li>
&lt;/ul>
&lt;p>例如：auto func = &amp;amp;MyClass::MemberFunction;（这里不能省略 &amp;amp;）。&lt;/p></description></item><item><title>57标准数组</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/57%E6%A0%87%E5%87%86%E6%95%B0%E7%BB%84/</link><pubDate>Tue, 10 Feb 2026 22:50:02 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/57%E6%A0%87%E5%87%86%E6%95%B0%E7%BB%84/</guid><description>&lt;ul>
&lt;li>本篇讲解&lt;mark>std::array&lt;/mark>，c++标准模板库中的标准数组类&lt;/li>
&lt;li>这是&lt;mark>静态&lt;/mark>数组，所谓的静态，即不会扩容缩小，数组一旦创建就要定义大小 &lt;del>和&lt;code>std::vector&lt;/code>不同&lt;/del> 、元素类型。&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;array&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;algorithm&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintArray1&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> array, &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> size;)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//如果不知道数组大小，使用模板。让编译器自己推断
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>size_t N&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> PrintArray(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>array&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>, N&lt;span style="color:#f92672">&amp;gt;&amp;amp;&lt;/span> data)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 在这里，N 会根据传入的数组自动推导
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (size_t i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> data.size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintArray&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>array&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>,&lt;span style="color:#ae81ff">5&lt;/span>&lt;span style="color:#f92672">&amp;gt;&amp;amp;&lt;/span> data)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> data.size();)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>array&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>, &lt;span style="color:#ae81ff">5&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> data;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> data.size() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data[&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//data[5] = 3;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//std::array能使用迭代器
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>sort(data.begin(), data.end());
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> data2[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	data[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>标准数组和普通数组，都是存放在栈上 &lt;del>标准向量是在堆上&lt;/del>&lt;/li>
&lt;li>有警告&lt;br>
&lt;img src="img/ly-20260210231113337.png" alt="" />&lt;/li>
&lt;/ul>
&lt;h1 id="datasize如何得知大小">&lt;code>data.size()&lt;/code>如何得知大小&lt;a class="anchor" href="#datasize%e5%a6%82%e4%bd%95%e5%be%97%e7%9f%a5%e5%a4%a7%e5%b0%8f">#&lt;/a>&lt;/h1>
&lt;p>&lt;code>std::array&lt;/code> 的大小（即数字 5）并不存储在程序运行时的内存里，是通过模板推导和常量替换实现的。&lt;/p></description></item><item><title>56auto</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/56auto/</link><pubDate>Tue, 10 Feb 2026 16:59:51 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/56auto/</guid><description>&lt;ul>
&lt;li>让cpp自动推导新声明变量的类型&lt;/li>
&lt;li>c++在一定程度上会转换为弱类型语言&lt;/li>
&lt;/ul>
&lt;h1 id="简单例子">简单例子&lt;a class="anchor" href="#%e7%ae%80%e5%8d%95%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">auto&lt;/span> x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;&lt;span style="color:#75715e">//int
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1.0&lt;/span>;&lt;span style="color:#75715e">//double
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">auto&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> a;&lt;span style="color:#75715e">//int
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> c &lt;span style="color:#f92672">=&lt;/span> y;&lt;span style="color:#75715e">//double
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> d &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3L&lt;/span>;&lt;span style="color:#75715e">//long
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> e &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5.3f&lt;/span>;&lt;span style="color:#75715e">//float
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> f &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;aa&amp;#34;&lt;/span>;&lt;span style="color:#75715e">//const char* //常量字符指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> b &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> c &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="进阶例子">进阶例子&lt;a class="anchor" href="#%e8%bf%9b%e9%98%b6%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>std&lt;span style="color:#f92672">::&lt;/span>string GetName1()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//返回值应该是const，修改项目设置后才能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 通过编译: c/c++-Language-Conformancemode-No
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">GetName2&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">auto&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;a&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string name1 &lt;span style="color:#f92672">=&lt;/span> GetName1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//string有一个可接受字符指针的隐式构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string name2 &lt;span style="color:#f92672">=&lt;/span> GetName2();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	name2.size();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果没有ide显示没办法一眼看出name3的类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> name3 &lt;span style="color:#f92672">=&lt;/span> GetName2(); &lt;span style="color:#75715e">//char*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//name3.size();//显然这里编译会失败
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>name3 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//&amp;#34;C&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="补充-接收字符指针如何构造string">补充-接收字符指针如何构造string&lt;a class="anchor" href="#%e8%a1%a5%e5%85%85-%e6%8e%a5%e6%94%b6%e5%ad%97%e7%ac%a6%e6%8c%87%e9%92%88%e5%a6%82%e4%bd%95%e6%9e%84%e9%80%a0string">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;cstring&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">// 为了使用 strlen 和 strcpy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">SimpleString&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Buffer; &lt;span style="color:#75715e">// 指向堆内存的指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_Size; &lt;span style="color:#75715e">// 字符串长度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 这就是那个“隐式构造函数”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 它接收一个 const char* 指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> SimpleString(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[Log] 调用了构造函数，接收指针: &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> (&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)string &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string); &lt;span style="color:#75715e">// 1. 计算长度
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> m_Buffer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>]; &lt;span style="color:#75715e">// 2. 在堆上申请内存（+1 是为了放 &amp;#39;\0&amp;#39;）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> memcpy(m_Buffer, string, m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>); &lt;span style="color:#75715e">// 3. 将内容从只读区拷贝到堆区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 析构函数：防止内存泄漏
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">~&lt;/span>SimpleString() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">delete&lt;/span>[] m_Buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 辅助函数，方便打印
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> m_Buffer &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">GetName2&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> (&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>; &lt;span style="color:#75715e">// 字符串字面量在只读区
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 发生了隐式转换！
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 编译器发现 GetName2() 返回 char*，而你需要 SimpleString
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 于是它自动调用了 SimpleString(&amp;#34;Cherno&amp;#34;)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> SimpleString name &lt;span style="color:#f92672">=&lt;/span> GetName2(); 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> name.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="相对有用的场景">相对有用的场景&lt;a class="anchor" href="#%e7%9b%b8%e5%af%b9%e6%9c%89%e7%94%a8%e7%9a%84%e5%9c%ba%e6%99%af">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//返回值应该是const，修改项目设置后才能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 通过编译: c/c++-Language-Conformancemode-No
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">GetName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//普通返回类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">auto&lt;/span> &lt;span style="color:#a6e22e">GetName1&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//后置返回类型1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">auto&lt;/span> &lt;span style="color:#a6e22e">GetName2&lt;/span>() &lt;span style="color:#f92672">-&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//后置返回类型2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//编译器要先看到a，b的类型，才能推断返回类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span> &lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T, &lt;span style="color:#66d9ef">typename&lt;/span> U&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">auto&lt;/span> Multiply(T a, U b) &lt;span style="color:#f92672">-&amp;gt;&lt;/span> &lt;span style="color:#66d9ef">decltype&lt;/span>(a&lt;span style="color:#f92672">*&lt;/span> b) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> a &lt;span style="color:#f92672">*&lt;/span> b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> strings;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	strings.push_back(&lt;span style="color:#e6db74">&amp;#34;apple&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	strings.push_back(&lt;span style="color:#e6db74">&amp;#34;orange&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//迭代器，是一个经过精心设计的类，内部最核心的成
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 员通常就是一个指向容器中某个位置的指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;::&lt;/span>iterator it &lt;span style="color:#f92672">=&lt;/span> strings.begin();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		it &lt;span style="color:#f92672">!=&lt;/span> strings.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>it &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;======1=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//类型过于冗长，用auto替代
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">auto&lt;/span> it &lt;span style="color:#f92672">=&lt;/span> strings.begin();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		it &lt;span style="color:#f92672">!=&lt;/span> strings.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>it &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;======2=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//类型别名 (Type Aliasing) [现代C++风格]：，支持模板别名（模板化using）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> UIterator &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;::&lt;/span>iterator;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//类型别名 (Type Aliasing) [传统C风格]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">typedef&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;::&lt;/span>iterator TIterator;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//类型过于冗长，用auto替代
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (UIterator it &lt;span style="color:#f92672">=&lt;/span> strings.begin();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		it &lt;span style="color:#f92672">!=&lt;/span> strings.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>it &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;======3=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//类型过于冗长，用auto替代
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (TIterator it &lt;span style="color:#f92672">=&lt;/span> strings.begin();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		it &lt;span style="color:#f92672">!=&lt;/span> strings.end(); it&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>it &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;======4=====&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;gt;&lt;/span> vectors;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vectors.push_back(&lt;span style="color:#e6db74">&amp;#34;hello&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vectors.push_back(&lt;span style="color:#e6db74">&amp;#34;world&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//s---&amp;gt;const std::string&amp;amp; s
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">auto&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> s : vectors) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> s &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>常见的使用场景：&lt;/p></description></item><item><title>55宏Macro</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/55%E5%AE%8FMacro/</link><pubDate>Tue, 10 Feb 2026 10:57:44 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/55%E5%AE%8FMacro/</guid><description>&lt;p>该集只是简单介绍一下&lt;/p>
&lt;ul>
&lt;li>
&lt;p>用预处理器对某些操作进行==类似宏处理&lt;del>实现自动化&lt;/del> ==&lt;/p>
&lt;/li>
&lt;li>
&lt;p>编译C++程序时，首先要进行预处理器处理&lt;/p>
&lt;ul>
&lt;li>以#开头的都叫做预处理器指令&lt;/li>
&lt;li>会被求值，然后处理好。再传递给编译器进行实际编译等操作&amp;mdash;文本编辑阶段（可以控制实际输入到编译器的代码）&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>工作阶段：宏是在 预处理（Preprocessing） 阶段处理的。这意味着在编译器真正看到你的代码并进行语法分析之前，宏就已经被处理完毕了。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>核心功能：宏本质上是 查找与替换（Find and Replace）。预处理器会扫描你的源代码，找到宏的名称，并将其替换为你定义的代码块或值。&lt;/p>
&lt;/li>
&lt;li>
&lt;p>预处理器（Preprocessor）先处理，模板（Templates）后处理。&lt;/p>
&lt;ul>
&lt;li>预处理器处理完后，编译器再进行模板实例化&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>建议：没有必要频繁的使用高级特性&lt;/p>
&lt;/li>
&lt;li>
&lt;p>宏是“翻译单元”私有的&lt;/p>
&lt;ul>
&lt;li>在 C++ 编译过程中，每个 .cpp 文件都是独立编译的，这被称为一个翻译单元（Translation Unit）。&lt;/li>
&lt;li>如果你想在多个 .cpp 文件中使用同一个宏，你应该把它放在一个头文件（.h）中，然后在需要的 .cpp 文件里&lt;code>#include&lt;/code>它。&lt;/li>
&lt;/ul>
&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//#define在改行代码之后，所以这行编译不过去
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//WAIT;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">#define WAIT std::cin.get()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//等待从控制台读取一行 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	WAIT;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>代码被预处理器处理后编译器看不出和普通代码有任何区别，我们用宏仅仅是改变了源代码的生成方式&lt;/p>
&lt;h1 id="例子1">例子1&lt;a class="anchor" href="#%e4%be%8b%e5%ad%901">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//等待从控制台读取一行 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//如果改行末尾带了;分号，也会被替换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#define WAIT std::cin.get()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#define OPEN_CURLY { 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#define SAY_HELLO std::cout &amp;lt;&amp;lt; &amp;#34;Hello1&amp;#34; &amp;lt;&amp;lt; std::endl
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>OPEN_CURLY
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	SAY_HELLO;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	WAIT;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="例子2">例子2&lt;a class="anchor" href="#%e4%be%8b%e5%ad%902">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#define LOG(x) std::cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; std::endl
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(&lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="分别处理调试和正式发布">分别处理调试和正式发布&lt;a class="anchor" href="#%e5%88%86%e5%88%ab%e5%a4%84%e7%90%86%e8%b0%83%e8%af%95%e5%92%8c%e6%ad%a3%e5%bc%8f%e5%8f%91%e5%b8%83">#&lt;/a>&lt;/h1>
&lt;p>Debug模式下预处理定义了 LY_DEBUG;&lt;/p></description></item><item><title>54栈内存和堆内存</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/54%E6%A0%88%E5%86%85%E5%AD%98%E5%92%8C%E5%A0%86%E5%86%85%E5%AD%98/</link><pubDate>Mon, 09 Feb 2026 22:16:40 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/54%E6%A0%88%E5%86%85%E5%AD%98%E5%92%8C%E5%A0%86%E5%86%85%E5%AD%98/</guid><description>&lt;p>栈和堆何时被使用，为何被使用，以及如何运作&lt;/p>
&lt;ul>
&lt;li>程序运行时，操作系统会把整个程序加载到内存中，同时分配大量物理内存&lt;/li>
&lt;li>栈和堆是&lt;mark>内存中&lt;/mark>实际存在的两个区域
&lt;ul>
&lt;li>栈具有预定义的大小，通常约2兆字节&lt;/li>
&lt;li>堆也有预定义默认值，随着应用程序运行，它会增长变化&lt;/li>
&lt;li>我们需要一个地方存储运行程序所需的数据，如局部变量、或者从文件读取数据&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>请求内存，也称内存分配&lt;/li>
&lt;/ul>
&lt;p>接下来看看在栈上分配一个整数，和在栈上分配其他数据的差异。与实际c++代码的堆相比&lt;/p>
&lt;h1 id="代码">代码&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector3&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y, z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector3()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>x(&lt;span style="color:#ae81ff">10&lt;/span>), y(&lt;span style="color:#ae81ff">11&lt;/span>), z(&lt;span style="color:#ae81ff">12&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在栈上分配内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">int&lt;/span> value &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">int&lt;/span> array[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		array[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		array[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		array[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		array[&lt;span style="color:#ae81ff">3&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		array[&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Vector3 vector;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> array &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>vector &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}&lt;span style="color:#75715e">//作用域结束后，该作用域内栈上分配所有内容都被弹出（内存被释放）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//在栈上分配内存和释放内存都只是移动栈指针，几乎没有性能损耗
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//new关键字分配堆内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> hvalue &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">*&lt;/span>hvalue &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> harray &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	harray[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	harray[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	harray[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	harray[&lt;span style="color:#ae81ff">3&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	harray[&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//()可以省略
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vector3&lt;span style="color:#f92672">*&lt;/span> hvector &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Vector3();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//必须手动释放内存
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">delete&lt;/span> hvalue;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span>[] harray;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span> hvector;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="栈">栈&lt;a class="anchor" href="#%e6%a0%88">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20260209224952058.png" alt="" />&lt;br>
&lt;img src="img/ly-20260209225100733.png" alt="" />&lt;/p></description></item><item><title>53(补充)字符串_数组_作为参数</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/53%E8%A1%A5%E5%85%85%E5%AD%97%E7%AC%A6%E4%B8%B2_%E6%95%B0%E7%BB%84_%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0/</link><pubDate>Mon, 09 Feb 2026 17:31:49 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/53%E8%A1%A5%E5%85%85%E5%AD%97%E7%AC%A6%E4%B8%B2_%E6%95%B0%E7%BB%84_%E4%BD%9C%E4%B8%BA%E5%8F%82%E6%95%B0/</guid><description>&lt;h1 id="普通数组退化-vs-字符串字面量退化">普通数组退化 vs. 字符串字面量退化&lt;a class="anchor" href="#%e6%99%ae%e9%80%9a%e6%95%b0%e7%bb%84%e9%80%80%e5%8c%96-vs-%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%ad%97%e9%9d%a2%e9%87%8f%e9%80%80%e5%8c%96">#&lt;/a>&lt;/h1>
&lt;h2 id="1-本质上的统一都是数组退化-array-decay">1. 本质上的统一：都是“数组退化” (Array Decay)&lt;a class="anchor" href="#1-%e6%9c%ac%e8%b4%a8%e4%b8%8a%e7%9a%84%e7%bb%9f%e4%b8%80%e9%83%bd%e6%98%af%e6%95%b0%e7%bb%84%e9%80%80%e5%8c%96-array-decay">#&lt;/a>&lt;/h2>
&lt;p>在 C++ 编译器眼中，无论是你定义的数组还是手写的字符串，它们的原始身份都是&lt;strong>固定长度的数组&lt;/strong>：&lt;/p>
&lt;ul>
&lt;li>&lt;code>int arr[5]&lt;/code> 的原始类型是：&lt;code>int[5]&lt;/code>&lt;/li>
&lt;li>&lt;code>&amp;quot;abc&amp;quot;&lt;/code> 的原始类型是：&lt;code>const char[4]&lt;/code>（包含隐藏的 &lt;code>\0&lt;/code>）&lt;/li>
&lt;/ul>
&lt;blockquote class='book-hint '>
&lt;p>&lt;strong>退化规则&lt;/strong>：当它们作为参数传递给接收指针的函数时，会执行相同的操作——&lt;strong>丢失长度信息，仅留下首元素的内存地址。&lt;/strong>&lt;/p>&lt;/blockquote>&lt;h2 id="2-它们的三大核心区别">2. 它们的三大核心区别&lt;a class="anchor" href="#2-%e5%ae%83%e4%bb%ac%e7%9a%84%e4%b8%89%e5%a4%a7%e6%a0%b8%e5%bf%83%e5%8c%ba%e5%88%ab">#&lt;/a>&lt;/h2>
&lt;p>虽然底层逻辑相同，但在内存布局和使用习惯上，它们有显著差异：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th style="text-align: left">维度&lt;/th>
 &lt;th style="text-align: left">普通数组 (如 &lt;code>int[]&lt;/code>)&lt;/th>
 &lt;th style="text-align: left">字符串字面量 (如 &lt;code>&amp;quot;abc&amp;quot;&lt;/code>)&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td style="text-align: left">&lt;strong>结束标志&lt;/strong>&lt;/td>
 &lt;td style="text-align: left">&lt;strong>无&lt;/strong>。必须额外传递 &lt;code>size&lt;/code> 参数。&lt;/td>
 &lt;td style="text-align: left">&lt;strong>有&lt;/strong>。自带“哨兵” &lt;code>\0&lt;/code> (Null Terminator)。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td style="text-align: left">&lt;strong>内存区域&lt;/strong>&lt;/td>
 &lt;td style="text-align: left">通常在 &lt;strong>栈 (Stack)&lt;/strong>，可读可写。&lt;/td>
 &lt;td style="text-align: left">在 &lt;strong>只读数据区 (Static Data)&lt;/strong>，不可修改。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td style="text-align: left">&lt;strong>退化后的类型&lt;/strong>&lt;/td>
 &lt;td style="text-align: left">&lt;code>int[5]&lt;/code> 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>→&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\rightarrow&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 &lt;code>int*&lt;/code>&lt;/td>
 &lt;td style="text-align: left">&lt;code>const char[4]&lt;/code> 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>→&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\rightarrow&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 &lt;code>const char*&lt;/code>&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h2 id="3-详细拆解">3. 详细拆解&lt;a class="anchor" href="#3-%e8%af%a6%e7%bb%86%e6%8b%86%e8%a7%a3">#&lt;/a>&lt;/h2>
&lt;h3 id="区别-a哨兵机制-the-terminator">&lt;strong>区别 A：哨兵机制 (The Terminator)&lt;/strong>&lt;a class="anchor" href="#%e5%8c%ba%e5%88%ab-a%e5%93%a8%e5%85%b5%e6%9c%ba%e5%88%b6-the-terminator">#&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>普通数组&lt;/strong>：函数拿到 &lt;code>int*&lt;/code> 后，完全不知道哪里是数组的终点。如果你不传 &lt;code>size&lt;/code>，函数极易越界。&lt;/li>
&lt;li>&lt;strong>字符串&lt;/strong>：虽然也退化成了 &lt;code>const char*&lt;/code>，但函数可以通过不断向后寻找 &lt;code>\0&lt;/code> 来确定长度（这就是 &lt;code>strlen&lt;/code> 的工作原理）。&lt;/li>
&lt;/ul>
&lt;h3 id="区别-b内存安全性">&lt;strong>区别 B：内存安全性&lt;/strong>&lt;a class="anchor" href="#%e5%8c%ba%e5%88%ab-b%e5%86%85%e5%ad%98%e5%ae%89%e5%85%a8%e6%80%a7">#&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>&lt;strong>普通数组&lt;/strong>：&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">int&lt;/span> arr[] &lt;span style="color:#f92672">=&lt;/span> {&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> arr[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">9&lt;/span>; &lt;span style="color:#75715e">// 完全合法，你拥有这块内存的写权限
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>字符串字面量：通常在&lt;strong>只读数据区（Static/Data Segment）&lt;/strong>。它虽然退化成了 &lt;code>const char*&lt;/code>，但你绝对不能尝试通过指针去修改它，否则程序会直接崩溃。&lt;/li>
&lt;/ul>
&lt;h3 id="区别-c退化后的类型">区别 C：退化后的类型&lt;a class="anchor" href="#%e5%8c%ba%e5%88%ab-c%e9%80%80%e5%8c%96%e5%90%8e%e7%9a%84%e7%b1%bb%e5%9e%8b">#&lt;/a>&lt;/h3>
&lt;ul>
&lt;li>&lt;code>int a[5]&lt;/code> 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>→&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\rightarrow&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 退化为 &lt;code>int*&lt;/code>&lt;/li>
&lt;li>&lt;code>&amp;quot;abc&amp;quot;&lt;/code> (即 &lt;code>const char[4]&lt;/code>) 
 

 
 
 
 
 
 
 &lt;span class="katex">&lt;math xmlns="http://www.w3.org/1998/Math/MathML">&lt;semantics>&lt;mrow>&lt;mo>→&lt;/mo>&lt;/mrow>&lt;annotation encoding="application/x-tex">\rightarrow&lt;/annotation>&lt;/semantics>&lt;/math>&lt;/span>
 退化为 &lt;code>const char*&lt;/code>（注意多了一个 const，因为字面量不可修改）。&lt;/li>
&lt;/ul>
&lt;h1 id="string及string引用传参对比">string及string引用传参对比&lt;a class="anchor" href="#string%e5%8f%8astring%e5%bc%95%e7%94%a8%e4%bc%a0%e5%8f%82%e5%af%b9%e6%af%94">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test1&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> s ) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test2&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string s ) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> test1(&lt;span style="color:#e6db74">&amp;#34;abc&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> test2(&lt;span style="color:#e6db74">&amp;#34;abc&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>特性&lt;/th>
 &lt;th>const std::string&amp;amp; s&lt;/th>
 &lt;th>const std::string s&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>内存身份&lt;/td>
 &lt;td>函数内部的 s 只是外部对象的别名&lt;/td>
 &lt;td>函数内部的 s 是一个全新的副本&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>拷贝次数&lt;/td>
 &lt;td>仅隐式转换产生的 1 次临时构造&lt;/td>
 &lt;td>转换构造 + 传参拷贝（共 1-2 次）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>推荐程度&lt;/td>
 &lt;td>极高（行业标准）&lt;/td>
 &lt;td>不推荐（除非你打算在函数里修改它）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>安全性&lt;/td>
 &lt;td>保证不会在函数内产生冗余副本&lt;/td>
 &lt;td>容易引发不必要的性能损耗&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table></description></item><item><title>53模板</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/53%E6%A8%A1%E6%9D%BF/</link><pubDate>Mon, 09 Feb 2026 14:28:16 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/53%E6%A8%A1%E6%9D%BF/</guid><description>&lt;p>template，能让你定义一个待编译的模版 &lt;del>让编译器用一组规则为你编译代码&lt;/del>&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>当我写一个函数时，我在函数中使用一个模板，我实际做的事类似蓝图的东西，当我决定调用那个函数时，&lt;mark>指定一些参数，他们决定了实际放入模板的代码&lt;/mark>。&lt;/p>&lt;/blockquote>&lt;h1 id="简单例子">简单例子&lt;a class="anchor" href="#%e7%ae%80%e5%8d%95%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//template表明这是个编译时求值的模板，这不是实际的函数，只有在调用时才会创建并编译成源代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//可以从实际参数中隐式获取T
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> Print(T value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Print(&lt;span style="color:#ae81ff">5&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//&amp;#34;5.5&amp;#34;被隐式转为const char[4]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Print(&lt;span style="color:#e6db74">&amp;#34;5.5&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Print(&lt;span style="color:#ae81ff">3.7&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="额外补充">额外补充&lt;a class="anchor" href="#%e9%a2%9d%e5%a4%96%e8%a1%a5%e5%85%85">#&lt;/a>&lt;/h2>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>模板定义&lt;/th>
 &lt;th>调用 Print(&amp;ldquo;5.5&amp;rdquo;) 时 T 的类型&lt;/th>
 &lt;th>说明&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>void Print(T value)&lt;/td>
 &lt;td>const char*&lt;/td>
 &lt;td>发生退化。传递的是地址。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>void Print(T&amp;amp; value)&lt;/td>
 &lt;td>const char[4]&lt;/td>
 &lt;td>不发生退化。传递的是数组的引用。&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>void Print(const T&amp;amp; value)&lt;/td>
 &lt;td>char[4]&lt;/td>
 &lt;td>不发生退化。T 本身是 char[4]。&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 它代表：我只接受一个含有 4个char的数组的“引用”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span> (&lt;span style="color:#f92672">&amp;amp;&lt;/span>value)[&lt;span style="color:#ae81ff">4&lt;/span>]) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// sizeof(value) == 4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 编译器知道这个数组刚好就是 4 个字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//数组的首地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> value) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// sizeof(value) == 8 (在64位系统上)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 编译器不知道这里有 4 个字符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="例子2">例子2&lt;a class="anchor" href="#%e4%be%8b%e5%ad%902">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//template表明这是个编译时求值的模板，这不是实际的函数，只有在调用时才会创建并编译成源代码(才会实际创建函数)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//可以从实际参数中隐式获取T
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">template&lt;/span>&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">typename&lt;/span> T&lt;span style="color:#f92672">&amp;gt;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//和上面一个意思
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//template&amp;lt;class T&amp;gt;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> Print(T value)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> value &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//显示指定T
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Print&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span>(&lt;span style="color:#ae81ff">5&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//让编译器自己推断T的类型
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Print(&lt;span style="color:#ae81ff">5&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="例子3">例子3&lt;a class="anchor" href="#%e4%be%8b%e5%ad%903">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20260209190725017.png" alt="" />&lt;/p></description></item><item><title>52处理多返回值</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/52%E5%A4%84%E7%90%86%E5%A4%9A%E8%BF%94%E5%9B%9E%E5%80%BC/</link><pubDate>Sun, 08 Feb 2026 23:14:14 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/52%E5%A4%84%E7%90%86%E5%A4%9A%E8%BF%94%E5%9B%9E%E5%80%BC/</guid><description>&lt;p>这篇讨论的是如何在函数返回两个值&lt;/p>
&lt;p>cherno推荐的方法是创建一个结构体并返回它&lt;/p>
&lt;h1 id="代码预备">代码预备&lt;a class="anchor" href="#%e4%bb%a3%e7%a0%81%e9%a2%84%e5%a4%87">#&lt;/a>&lt;/h1>
&lt;p>为了演示，本篇使用了string，为了顺便探讨性能（视频中没提到），我写了一个string.h 和string.cpp打印相关信息&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//String.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once &lt;/span>&lt;span style="color:#75715e">// 防止头文件被重复包含
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">String&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_Buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 默认构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> String() &lt;span style="color:#f92672">:&lt;/span> m_Buffer(&lt;span style="color:#66d9ef">nullptr&lt;/span>), m_Size(&lt;span style="color:#ae81ff">0&lt;/span>) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 拷贝构造函数（深拷贝）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">//拷贝构造函数 (String a = b;)：当你在创建一个新的对象，并用已有的对象初始化它时调用。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#f92672">~&lt;/span>String();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 运算符重载
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>[](&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> index);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 赋值运算符重载 (a = b;)：当两个对象都已经存在（已经构造完毕），你只是想把其中一个的值覆盖给另一个时调用。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other); 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 友元函数：重载 &amp;lt;&amp;lt; 运算符
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">friend&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream, &lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 测试函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> mytest() { &lt;span style="color:#66d9ef">return&lt;/span> m_Size; } &lt;span style="color:#75715e">// 简单的内联函数可以直接写在类内
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>};&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;String.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;cstring&amp;gt;&lt;/span>&lt;span style="color:#75715e"> &lt;/span>&lt;span style="color:#75715e">// 必须包含 cstring 才能使用 strlen 和 memcpy
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>String&lt;span style="color:#f92672">::&lt;/span>String(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_Size &lt;span style="color:#f92672">=&lt;/span> strlen(string);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_Buffer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	memcpy(m_Buffer, string, m_Size);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_Buffer[m_Size] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;\0&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 拷贝构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>String&lt;span style="color:#f92672">::&lt;/span>String(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">:&lt;/span> m_Size(other.m_Size)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Copied String!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_Buffer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	memcpy(m_Buffer, other.m_Buffer, m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//赋值运算符 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>String&lt;span style="color:#f92672">&amp;amp;&lt;/span> String&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Assignment Operator Called!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> other &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 1. 自赋值检查 (防止 s1 = s1 的骚操作)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#66d9ef">this&lt;/span> &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 2. 释放当前对象旧的内存，防止内存泄漏
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 3. 申请新空间并拷贝内容
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	m_Size &lt;span style="color:#f92672">=&lt;/span> other.m_Size;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	m_Buffer &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	memcpy(m_Buffer, other.m_Buffer, m_Size &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 4. 返回对象自身，支持链式赋值 (a = b = c)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>String&lt;span style="color:#f92672">::~&lt;/span>String()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">delete&lt;/span>[] m_Buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 下标运算符重载
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> String&lt;span style="color:#f92672">::&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span>[](&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> index)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> m_Buffer[index];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 友元函数定义（注意：定义时不需要加 String::，也不需要加 friend 关键字）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream, &lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> string)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	stream &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> string.m_Buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> stream;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="方法1使用引用">方法1：使用引用&lt;a class="anchor" href="#%e6%96%b9%e6%b3%951%e4%bd%bf%e7%94%a8%e5%bc%95%e7%94%a8">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;String.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">ParseShader&lt;/span>(String&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertexSource, String&lt;span style="color:#f92672">&amp;amp;&lt;/span> fragmentSource)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//假设vs，fs最终计算值是abc、def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String vs &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;abc&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String fs &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;def&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这两行代码执行的是 字符串赋值(内部会拷贝)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vertexSource &lt;span style="color:#f92672">=&lt;/span> vs;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	fragmentSource &lt;span style="color:#f92672">=&lt;/span> fs;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String vs, fs;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ParseShader(vs, fs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vs &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std &lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> fs &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Assignment Operator Called!abc
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Assignment Operator Called!def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">abc
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="方法2使用指针">方法2：使用指针&lt;a class="anchor" href="#%e6%96%b9%e6%b3%952%e4%bd%bf%e7%94%a8%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;String.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">ParseShader&lt;/span>(String&lt;span style="color:#f92672">*&lt;/span> vertexSource, String&lt;span style="color:#f92672">*&lt;/span> fragmentSource)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//假设vs，fs最终计算值是abc、def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String vs &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;abc&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String fs &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;def&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这两行代码执行的是 字符串赋值(内部会拷贝)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (vertexSource) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">*&lt;/span>vertexSource &lt;span style="color:#f92672">=&lt;/span> vs;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (fragmentSource) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">*&lt;/span>fragmentSource &lt;span style="color:#f92672">=&lt;/span> fs;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String vs, fs;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ParseShader(&lt;span style="color:#f92672">&amp;amp;&lt;/span>vs, &lt;span style="color:#f92672">&amp;amp;&lt;/span>fs);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这种方式允许空指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//ParseShader(nullptr, &amp;amp;fs);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vs &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> fs &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Assignment Operator Called!abc
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Assignment Operator Called!def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">abc
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="同类型方法3返回数组指针">(同类型)方法3：返回(数组)指针&lt;a class="anchor" href="#%e5%90%8c%e7%b1%bb%e5%9e%8b%e6%96%b9%e6%b3%953%e8%bf%94%e5%9b%9e%e6%95%b0%e7%bb%84%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;String.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>String&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">ParseShader&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//假设vs，fs最终计算值是abc、def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//vs,fs先在栈上创建（但String成员m_Buffer是指向堆）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String vs &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;abc&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String fs &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;def&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这种语法在c++20才能编译通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> String[]{ vs,fs };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里不知道数组有多大
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	String&lt;span style="color:#f92672">*&lt;/span> result &lt;span style="color:#f92672">=&lt;/span>ParseShader();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> result[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> result[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Assignment Operator Called!abc
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Assignment Operator Called!def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">abc
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">def
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;em>分析：&lt;/em>&lt;/p></description></item><item><title>51创建并使用库</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/51%E5%88%9B%E5%BB%BA%E5%B9%B6%E4%BD%BF%E7%94%A8%E5%BA%93/</link><pubDate>Sun, 08 Feb 2026 19:02:14 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/51%E5%88%9B%E5%BB%BA%E5%B9%B6%E4%BD%BF%E7%94%A8%E5%BA%93/</guid><description>&lt;p>如何在vs中设置多个项目，以及如何创建一个能在所有项目中使用的库&lt;/p>
&lt;h1 id="51创建并使用库">51创建并使用库&lt;a class="anchor" href="#51%e5%88%9b%e5%bb%ba%e5%b9%b6%e4%bd%bf%e7%94%a8%e5%ba%93">#&lt;/a>&lt;/h1>
&lt;p>先以Game51命名创建一个项目&lt;br>
&lt;img src="img/ly-20260208192031864.png" alt="" />&lt;/p>
&lt;p>文件夹查看&lt;br>
&lt;img src="img/ly-20260208192053400.png" alt="" />&lt;/p>
&lt;p>再新建一个项目，项目名为Engine&lt;/p>
&lt;p>&lt;img src="img/ly-20260208195515662.png" alt="" />&lt;/p>
&lt;p>此时&lt;/p>
&lt;p>&lt;img src="img/ly-20260208195641775.png" alt="" />&lt;/p>
&lt;hr>
&lt;p>现在确保设置Game51为应用程序&lt;/p>
&lt;p>&lt;img src="img/ly-20260208200254073.png" alt="" />&lt;/p>
&lt;p>Engine项目配置为静态库&lt;/p>
&lt;p>&lt;img src="img/ly-20260208200507567.png" alt="" />&lt;/p>
&lt;h1 id="创建文件夹及文件">创建文件夹及文件&lt;a class="anchor" href="#%e5%88%9b%e5%bb%ba%e6%96%87%e4%bb%b6%e5%a4%b9%e5%8f%8a%e6%96%87%e4%bb%b6">#&lt;/a>&lt;/h1>
&lt;p>show All Files&lt;/p>
&lt;p>&lt;img src="img/ly-20260208215039688.png" alt="" />&lt;/p>
&lt;p>目录结构&lt;/p>
&lt;p>&lt;img src="img/ly-20260208221818789.png" alt="" />&lt;/p>
&lt;h1 id="静态链接库engine项目">（静态链接库）Engine项目&lt;a class="anchor" href="#%e9%9d%99%e6%80%81%e9%93%be%e6%8e%a5%e5%ba%93engine%e9%a1%b9%e7%9b%ae">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//src/Engine.h
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#pragma once
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> engine {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintMessage&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//不能这么写,说明:: 被称为作用域解析运算符。它的逻辑
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 是：你只能引用一个已经存在的名字空间。而这里正在定义
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//所以不存在
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//void engine::PrintMessage();
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">///src/Engine.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Engine.h&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">namespace&lt;/span> engine {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintMessage&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello World!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//或者这么写
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//void engine::PrintMessage()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//	std::cout &amp;lt;&amp;lt; &amp;#34;Hello World!&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="使用静态链接库game51项目中">（使用静态链接库）Game51项目中&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8%e9%9d%99%e6%80%81%e9%93%be%e6%8e%a5%e5%ba%93game51%e9%a1%b9%e7%9b%ae%e4%b8%ad">#&lt;/a>&lt;/h1>
&lt;h2 id="处理头文件的两个方法">处理头文件的两个方法&lt;a class="anchor" href="#%e5%a4%84%e7%90%86%e5%a4%b4%e6%96%87%e4%bb%b6%e7%9a%84%e4%b8%a4%e4%b8%aa%e6%96%b9%e6%b3%95">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Application.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//添加头文件-方法1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//#include &amp;#34;../../Engine/src/Engine.h&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//直接声明-方法0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//namespace engine {
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//	void PrintMessage();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	engine&lt;span style="color:#f92672">::&lt;/span>PrintMessage();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="处理头文件的第3个方法">处理头文件的第3个方法&lt;a class="anchor" href="#%e5%a4%84%e7%90%86%e5%a4%b4%e6%96%87%e4%bb%b6%e7%9a%84%e7%ac%ac3%e4%b8%aa%e6%96%b9%e6%b3%95">#&lt;/a>&lt;/h2>
&lt;p>右键项目Game51属性修改&lt;br>
&lt;img src="img/ly-20260208222335125.png" alt="" />&lt;/p></description></item><item><title>50使用动态库</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/50%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E5%BA%93/</link><pubDate>Sun, 08 Feb 2026 16:02:50 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/50%E4%BD%BF%E7%94%A8%E5%8A%A8%E6%80%81%E5%BA%93/</guid><description>&lt;p>动态链接是什么，以及如何使用&lt;/p>
&lt;ul>
&lt;li>动态链接是在运行时发生的链接，当你实际启动可执行文件时，动态链接库加载时 它并非可执行文件的一部分，此时动态链接库被载入内存。意味着&lt;mark>运行时会动态链接另一个库&lt;/mark>，然后运行应用程序 载入一个额外文件到内存。
&lt;ul>
&lt;li>这种情况下，可执行文件实际上需要某些库存在（外部文件）。比如windows系统经常出现“缺少某些dll文件无法启动”&lt;/li>
&lt;li>可执行文件了解动态链接库，&lt;mark>可执行文件是一个独立文件&lt;/mark>，在运行时加载的&lt;mark>独立&lt;/mark>模块。但也可以&lt;mark>加载动态链接库&lt;/mark>，他会在运行时查找并加载动态库，然后可以获取函数指针/动态库中任何内容&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>静态链接是在编译时发生的链接，当你编译一个静态库时，将它链接到可执行文件、应用程序或动态库中。即：&lt;mark>直接获取静态库的内容，然后把它和其他二进制数据放到一起&lt;/mark>，静态库实际存在于可执行文件或动态库中，所以编译器、链接器完全清楚这些代码，并会对此进行优化&lt;/li>
&lt;/ul>
&lt;blockquote class='book-hint '>
&lt;p>当我们说“链接到一个动态库”时，实际上是指在创建（生成）那个 DLL 的时候，把静态库的代码塞进去。&lt;/p>&lt;/blockquote>&lt;p>补充：动态链接包括“隐式链接” &lt;del>需要 header (.h) 和 import library (.lib)&lt;/del> 和“显示链接” &lt;del>编译阶段完全不认识这个 DLL，也不需要 .lib 导入库。用法： 运行时使用 Windows API 函数（如 LoadLibrary 和 GetProcAddress）去手动加载。&lt;/del>&lt;/p>
&lt;h1 id="50使用动态库">50使用动态库&lt;a class="anchor" href="#50%e4%bd%bf%e7%94%a8%e5%8a%a8%e6%80%81%e5%ba%93">#&lt;/a>&lt;/h1>
&lt;p>复制Dependencies文件夹到根目录&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">λ&lt;/span> tree Dependencies &lt;span style="color:#f92672">/&lt;/span>f
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>CHERNOCPP&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>HELLOWORLD49&lt;span style="color:#960050;background-color:#1e0010">\&lt;/span>DEPENDENCIES
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>GLFW
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>include
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>GLFW
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> glfw3.h
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> glfw3native.h
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#960050;background-color:#1e0010">│&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>vc2022
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> glfw3.dll
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> glfw3.lib
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> glfw3dll.lib
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> glfw3_mt.lib&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>静态链接和动态链接都是用同一部分的头文件&lt;/p>
&lt;p>&lt;img src="img/ly-20260208172423520.png" alt="" />&lt;/p>
&lt;p>&lt;img src="img/ly-20260208172448298.png" alt="" />&lt;/p>
&lt;p>目前按ctrl+f7已经能正常编译&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>glw3dll.lib &lt;del>glfw3dll.lib不存代码，只有地址&lt;/del> ，这是指向glw3.dll的一系列指针，所以我们在运行时无需实际检测所有内容的位置，&lt;mark>这两者同时编译很重要&lt;/mark>，因为在运行时如果尝试使用不同静态库与DLL链接，你可能会遇到函数不匹配，并且函数指针会出现内存地址错误。但是这里是由glfw分发的，所以glw3.dll和glw3dll.lib是同时编译的，而且他们直接相互关联，这两者不能分开。&lt;/p>&lt;/blockquote>&lt;p>接下来设置库文件&lt;/p>
&lt;p>&lt;img src="img/ly-20260208173428008.png" alt="" />&lt;/p>
&lt;p>&lt;img src="img/ly-20260208173520524.png" alt="" />&lt;/p>
&lt;p>右键项目并build成功。但是目前如果会提示找不到dll文件&lt;/p></description></item><item><title>49使用静态库</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/49%E4%BD%BF%E7%94%A8%E9%9D%99%E6%80%81%E5%BA%93/</link><pubDate>Sat, 07 Feb 2026 23:31:35 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/49-80/49%E4%BD%BF%E7%94%A8%E9%9D%99%E6%80%81%E5%BA%93/</guid><description>&lt;h1 id="49使用静态库">49使用静态库&lt;a class="anchor" href="#49%e4%bd%bf%e7%94%a8%e9%9d%99%e6%80%81%e5%ba%93">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>从github库或其他敌法check out代码块，在那个代码库里能直接得到编译所需的一切，并运行应用程序或项目等，无需使用包管理器&lt;/li>
&lt;li>倾向于实际保留依赖项的版本，实际解决方案中二进制的版本。实际项目文件夹中有物理二进制文件的副本，或者是源码&lt;/li>
&lt;/ul>
&lt;p>要&lt;mark>自己编译&lt;/mark>？或者直接链接预构建的二进制文件&lt;/p>
&lt;ul>
&lt;li>建议直接添加另一个项目（依赖项的源代码），然后编译成静态库或动态库&lt;/li>
&lt;li>非大型项目，可以直接链接二进制文件（无需源代码）&lt;/li>
&lt;/ul>
&lt;p>本篇要处理的是GLFW的库&lt;/p>
&lt;p>选择二进制版本 (32位 vs 64位)，这取决于你的&lt;mark>目标应用程序架构&lt;/mark>，而不是你的操作系统。&lt;/p>
&lt;p>比如现在我要制作一个32位应用程序&lt;br>
&lt;img src="img/ly-20260208082108851.png" alt="" />&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//结构
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//里面通常是 HTML 格式的 API 手册。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>docs
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>html
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>search
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>include
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>GLFW
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//含义： 针对 MinGW 编译器的版本（通常配合 GCC 使用）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//用途： 如果你不在 Windows 上用 Visual Studio，而是用 CLion、Code::Blocks 或者直接在命令行用 g++ 编译，你需要链接这个文件夹里的库（通常是 .a 文件而非 .lib）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>mingw&lt;span style="color:#f92672">-&lt;/span>w64 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>libglfw3.a &lt;span style="color:#75715e">//(静态库)： 如果你用 MinGW 编译器并想进行静态链接
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>glfw3.dll &lt;span style="color:#75715e">//(动态链接库)： 这是库的实体。 如果你选择动态链接，这个文件必须在运行时放在你的 .exe 旁边
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">│&lt;/span> &lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>libglfw3dll.a &lt;span style="color:#75715e">//给编译器看的“目录”。 当你选择动态链接时，你不是直接链接 .dll，而是链接这个 .a 文件。 它告诉编译器：“真正的代码在 glfw3.dll 里，你先编译通过，运行时再去调它。”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//如果你的项目配置为使用通用的 Windows 10/11 SDK 运行时，有时需要专门链接这个版本的库。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#66d9ef">static&lt;/span>&lt;span style="color:#f92672">-&lt;/span>ucrt
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//以下是库文件 (.lib)，是给 链接器 用的。之所以有这么多，是因为 C++ 的二进制兼容性比较复杂，库的版本必须尽量与你使用的 Visual Studio 版本匹配
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>vc2013
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>vc2015
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>vc2017
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">├─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>vc2019
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#960050;background-color:#1e0010">└─&lt;/span>lib&lt;span style="color:#f92672">-&lt;/span>vc2022&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>库由&lt;em>包含目录includes&lt;/em>和&lt;em>库目录libraries&lt;/em>组成&lt;/p></description></item><item><title>47优化cpp中stdvector的使用</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/47%E4%BC%98%E5%8C%96cpp%E4%B8%ADstdvector%E7%9A%84%E4%BD%BF%E7%94%A8/</link><pubDate>Sat, 07 Feb 2026 07:47:28 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/47%E4%BC%98%E5%8C%96cpp%E4%B8%ADstdvector%E7%9A%84%E4%BD%BF%E7%94%A8/</guid><description>&lt;p>&lt;em>预习&lt;/em>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vertex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y, z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//有了其他的构造函数，如果需要用到无参构造函数，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//就必须手动写一个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vertex()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//因为有构造函数了，所以Vertex 结构体不是一个聚合类型(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 有构造函数)，所以要使用显示构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 使 Vertex v = { 1,2,3 }; 编译通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vertex(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y, &lt;span style="color:#66d9ef">float&lt;/span> z)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>y &lt;span style="color:#f92672">=&lt;/span> y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>z &lt;span style="color:#f92672">=&lt;/span> z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//参数必须是&amp;amp;，原因如下:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//1. 当你尝试通过 Vertex a = b; 调用复制构造函数时，你需要将 b 传递给参数 other。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. 在 C++ 中，按值传递（Pass by Value）参数本身就会触发一次复制。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3. 为了复制 b 到 other，编译器又需要调用复制构造函数。[死循环了]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//因为main中使用 vector.push({1,2,3}) 需要将临时对象拷贝到vector中，所以这里的参数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//必须是const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vertex(&lt;span style="color:#66d9ef">const&lt;/span> Vertex&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;copied constructor handled&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> vertex.x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>y &lt;span style="color:#f92672">=&lt;/span> vertex.y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>z &lt;span style="color:#f92672">=&lt;/span> vertex.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*virtual*/&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Vertex()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;destructor handled&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream, &lt;span style="color:#66d9ef">const&lt;/span> Vertex&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	stream &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertex.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertex.y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertex.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> stream;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//使用引用避免复制整个数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Function&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vertex&lt;span style="color:#f92672">&amp;gt;&amp;amp;&lt;/span> vertices)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vertex&lt;span style="color:#f92672">&amp;gt;&lt;/span> vertices;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//vertices.push_back({ 1,2,3 });
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::cout &amp;lt;&amp;lt; &amp;#34;==0===&amp;#34; &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//vertices.push_back({ 4,5,6 });
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//对上面两行代码优化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 1. 预先分配内存，防止搬家
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vertices.reserve(&lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// 2. 原地构造，防止临时拷贝
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vertices.emplace_back(&lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#ae81ff">2&lt;/span>, &lt;span style="color:#ae81ff">3&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==0===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//超出容量，会拷贝原来的{1,2,3}到新数组，并且销毁
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 原数组中的{1,2,3}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vertices.emplace_back(&lt;span style="color:#ae81ff">4&lt;/span>, &lt;span style="color:#ae81ff">5&lt;/span>, &lt;span style="color:#ae81ff">6&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==1===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Function(vertices);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==2===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vertices.erase(vertices.begin() &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;==3===&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (Vertex&lt;span style="color:#f92672">&amp;amp;&lt;/span> v : vertices)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copied constructor handled //第一个临时对象复制到vector中之后，马上又销毁了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">destructor handled
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==0===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copied constructor handled //空间不够了，需要把第一个元素复制到新数组中。第二个元素创建临时对象，并复制到新数组中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">copied constructor handled
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">destructor handled //旧的数组中的第一个元素被销毁了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">destructor handled //第二个元素的临时对象被销毁了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==1===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==2===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">destructor handled
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==3===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">1,2,3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*优化后不需要把临时对象复制到vector中，也不需要销毁临时对象了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==1===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==2===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">destructor handled
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">==3===
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">1,2,3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;hr>
&lt;p>了解环境是优化过程中最重要的事情之一&lt;/p></description></item><item><title>46动态数组</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/46%E5%8A%A8%E6%80%81%E6%95%B0%E7%BB%84/</link><pubDate>Fri, 06 Feb 2026 14:21:51 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/46%E5%8A%A8%E6%80%81%E6%95%B0%E7%BB%84/</guid><description>&lt;ul>
&lt;li>动态数组，特别是讨论标准向量类&lt;/li>
&lt;li>要习惯CPP的标准库（标准模版库）&lt;/li>
&lt;li>标准模版库包含了各种容器、迭代器、算法、仿函数&lt;/li>
&lt;/ul>
&lt;hr>
&lt;ul>
&lt;li>容器的数据类型由程序员自己决定&lt;/li>
&lt;li>cpp提供了一个Vector的类，在std命名空间中，可以调整大小，也可以不指定初始大小&lt;/li>
&lt;li>本系列会重写C++中的数据结构，优化后比标准模版库中的快很多&lt;/li>
&lt;/ul>
&lt;p>&lt;code>std::vector&lt;/code> 的实际工作方式：&lt;/p>
&lt;p>当超出实际的分配大小时。当创建一个向量，可能会先分配10个元素大小的空间，当超出这个大小时，会在内存中创建一个比原来更大的数组，并把所有内容复制过去，然后删除旧数组。这样就有了一个更大存储空间的新数组&lt;/p>
&lt;h1 id="46动态数组">46动态数组&lt;a class="anchor" href="#46%e5%8a%a8%e6%80%81%e6%95%b0%e7%bb%84">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vertex&lt;/span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y, z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*virtual*/&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//main()中
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>Vertex v &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span> };&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>聚合初始化（Aggregate Initialization），Vertex 结构体是一个聚合类型（Aggregate Type）。在 C++ 中，如果一个类或结构体满足以下条件：&lt;/p>
&lt;ul>
&lt;li>没有显式定义的构造函数。&lt;/li>
&lt;li>成员变量是公有的（public）。&lt;/li>
&lt;li>没有基类（没有继承）。&lt;/li>
&lt;li>没有虚函数。&lt;/li>
&lt;/ul>
&lt;p>那么你可以使用大括号 {} 直接按顺序为成员变量赋值。&lt;/p>
&lt;h1 id="vector的基本使用">vector的基本使用&lt;a class="anchor" href="#vector%e7%9a%84%e5%9f%ba%e6%9c%ac%e4%bd%bf%e7%94%a8">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;vector&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Test&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vertex&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y, z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//有了其他的构造函数，如果需要用到无参构造函数，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//就必须手动写一个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vertex()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//因为有构造函数了，所以Vertex 结构体不是一个聚合类型(
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 有构造函数)，所以要使用显示构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 使 Vertex v = { 1,2,3 }; 编译通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vertex(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y, &lt;span style="color:#66d9ef">float&lt;/span> z)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>y &lt;span style="color:#f92672">=&lt;/span> y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>z &lt;span style="color:#f92672">=&lt;/span> z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//参数必须是&amp;amp;，原因如下:
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//1. 当你尝试通过 Vertex a = b; 调用复制构造函数时，你需要将 b 传递给参数 other。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. 在 C++ 中，按值传递（Pass by Value）参数本身就会触发一次复制。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//3. 为了复制 b 到 other，编译器又需要调用复制构造函数。[死循环了]
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//因为main中使用 vector.push({1,2,3}) 需要将临时对象拷贝到vector中，所以这里的参数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//必须是const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vertex(&lt;span style="color:#66d9ef">const&lt;/span> Vertex&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;copied constructor handled&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> vertex.x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>y &lt;span style="color:#f92672">=&lt;/span> vertex.y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>z &lt;span style="color:#f92672">=&lt;/span> vertex.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*virtual*/&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Vertex()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;destructor handled&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream, &lt;span style="color:#66d9ef">const&lt;/span> Vertex&lt;span style="color:#f92672">&amp;amp;&lt;/span> vertex)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	stream &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertex.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertex.y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertex.z;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> stream;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vertex vertices1[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vertex&lt;span style="color:#f92672">*&lt;/span> vertices2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Vertex[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;gt;&lt;/span> myarray;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//存储Vertex对象，则动态数组的内存是连续的，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//其中的Vertext对象会按行排列
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//问题是：实际要调整向量大小时得复制所有(类)数据，但内存连续性
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 带来的读取速度提升通常远超扩容时的开销
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vertex&lt;span style="color:#f92672">&amp;gt;&lt;/span> vertices;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//存储Vertext指针,实际要调整向量大小是只是复制指针地址(一个数字)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//，即实际数据的内存地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>vector&lt;span style="color:#f92672">&amp;lt;&lt;/span>Vertex&lt;span style="color:#f92672">*&amp;gt;&lt;/span> vertices4;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---1---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vertex v &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里演示vertices的使用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---2---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vertices.push_back({ &lt;span style="color:#ae81ff">1&lt;/span>,&lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span> });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---3---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	vertices.push_back({ &lt;span style="color:#ae81ff">4&lt;/span>,&lt;span style="color:#ae81ff">5&lt;/span>,&lt;span style="color:#ae81ff">6&lt;/span> });
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---4---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> vertices.size(); i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//c++对[]进行了重载
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> vertices[i] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---5---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里会把每个Vertex复制到v
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (Vertex v : vertices)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---6---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//避免复制
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">for&lt;/span> (Vertex&lt;span style="color:#f92672">&amp;amp;&lt;/span> v : vertices)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> v &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//clear() 会移除容器中的所有元素，但通常不一定会立即释放底层内存（容量不变），它只是销毁现有的对象。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	vertices.clear();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="解释一下verticespush_back1-2-3">解释一下&lt;code>vertices.push_back({1, 2, 3});&lt;/code>&lt;a class="anchor" href="#%e8%a7%a3%e9%87%8a%e4%b8%80%e4%b8%8bverticespush_back1-2-3">#&lt;/a>&lt;/h2>
&lt;p>当你执行 &lt;code>vertices.push_back({1, 2, 3});&lt;/code> 时，逻辑确实是：在 vector 内部的内存中，通过调用复制构造函数来构造一个属于 vector 自己的对象。&lt;/p></description></item><item><title>45箭头运算符</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/45%E7%AE%AD%E5%A4%B4%E8%BF%90%E7%AE%97%E7%AC%A6/</link><pubDate>Wed, 04 Feb 2026 11:24:32 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/45%E7%AE%AD%E5%A4%B4%E8%BF%90%E7%AE%97%E7%AC%A6/</guid><description>&lt;p>在 C++ 中，-&amp;gt; 运算符有一个独特的“递归”特性。当你写下 entity-&amp;gt;Print() 时，编译器会查看 entity 的类型：&lt;/p>
&lt;ul>
&lt;li>如果 entity 是原生指针：它直接解引用并访问成员。&lt;/li>
&lt;li>如果 entity 是一个对象（类实例）：
&lt;ol>
&lt;li>编译器会调用你重载的 operator-&amp;gt;()。&lt;/li>
&lt;li>这个函数必须返回两样东西之一：要么是一个原生指针，要么是另一个重载了 -&amp;gt; 的对象。&lt;/li>
&lt;li>编译器拿到返回的指针后，自动再次对它使用箭头操作，直到找到最终的成员。&lt;/li>
&lt;/ol>
&lt;/li>
&lt;/ul>
&lt;h1 id="箭头运算符的使用及重载">箭头运算符的使用及重载&lt;a class="anchor" href="#%e7%ae%ad%e5%a4%b4%e8%bf%90%e7%ae%97%e7%ac%a6%e7%9a%84%e4%bd%bf%e7%94%a8%e5%8f%8a%e9%87%8d%e8%bd%bd">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Print() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello!x=&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//创建这个类的对象时传入一个堆上的对象，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//可以使用堆对象，且堆对象会被自动释放
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ScopePtr&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ScopePtr(Entity&lt;span style="color:#f92672">*&lt;/span> entity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Obj(entity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>ScopePtr()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;release m_Obj&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">GetObject&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	} 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	e.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//取消引用后用 .函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity&lt;span style="color:#f92672">*&lt;/span> ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">&amp;amp;&lt;/span> entity &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>ptr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//entity.Print();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//(*ptr).Print();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ptr&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ptr&lt;span style="color:#f92672">-&amp;gt;&lt;/span>Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		ScopePtr entity &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Entity();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		entity.GetObject()&lt;span style="color:#f92672">-&amp;gt;&lt;/span>Print(); 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="重载箭头运算符">重载箭头运算符&lt;a class="anchor" href="#%e9%87%8d%e8%bd%bd%e7%ae%ad%e5%a4%b4%e8%bf%90%e7%ae%97%e7%ac%a6">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> Print() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello!x=&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//创建这个类的对象时传入一个堆上的对象，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//可以使用堆对象，且堆对象会被自动释放
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">ScopePtr&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ScopePtr(Entity&lt;span style="color:#f92672">*&lt;/span> entity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Obj(entity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>ScopePtr()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;release m_Obj&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">GetObject&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//1. 告诉编译器：“我把内部的指针给你用，但你只能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 看，不能改指针指向的那个 Entity。”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2. 右边的const：“这个函数是一个‘只读’函数，它不会修改
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// ScopedPtr 对象内部的任何成员变量。”，而且，他的返回值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不能调用非const函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Obj;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	e.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//取消引用后用 .函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity&lt;span style="color:#f92672">*&lt;/span> ptr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">&amp;amp;&lt;/span> entity &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">*&lt;/span>ptr;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//entity.Print();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//(*ptr).Print();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ptr&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	ptr&lt;span style="color:#f92672">-&amp;gt;&lt;/span>Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//隐式转换，编译器会寻找匹配的构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//等同于：ScopePtr entity(new Entity()); // 直接初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 或者 ScopePtr entity = ScopePtr(new Entity()); // 显式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		ScopePtr entity &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Entity();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		entity.GetObject()&lt;span style="color:#f92672">-&amp;gt;&lt;/span>Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		entity&lt;span style="color:#f92672">-&amp;gt;&lt;/span>Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>对于&lt;code>ScopePtr entity = new Entity();&lt;/code>，编译器的逻辑&lt;/p></description></item><item><title>44_1使用memcpy的注意事项</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/44_1%E4%BD%BF%E7%94%A8memcpy%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/</link><pubDate>Tue, 03 Feb 2026 10:28:04 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/44_1%E4%BD%BF%E7%94%A8memcpy%E7%9A%84%E6%B3%A8%E6%84%8F%E4%BA%8B%E9%A1%B9/</guid><description>&lt;h1 id="毁掉多态篡改虚函数表指针-vptr">毁掉多态：篡改虚函数表指针 (vptr)&lt;a class="anchor" href="#%e6%af%81%e6%8e%89%e5%a4%9a%e6%80%81%e7%af%a1%e6%94%b9%e8%99%9a%e5%87%bd%e6%95%b0%e8%a1%a8%e6%8c%87%e9%92%88-vptr">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;cstring&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">virtual&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> SayName() { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;I am Entity&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Player&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> Entity {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">void&lt;/span> SayName() &lt;span style="color:#66d9ef">override&lt;/span> { std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;I am Player&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>(Entity&lt;span style="color:#f92672">*&lt;/span> e) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> e&lt;span style="color:#f92672">-&amp;gt;&lt;/span>SayName(); &lt;span style="color:#75715e">// 强制程序通过虚表查找
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Entity base;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Player p1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Before memcpy: &amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Print(&lt;span style="color:#f92672">&amp;amp;&lt;/span>p1); &lt;span style="color:#75715e">// 应该输出 I am Player
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//base复制给p1，但是p1的虚函数表却指向的是Entity的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 暴力覆盖！把 base 的内存（包含 Entity 的 vptr）强行塞进 p1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>memcpy(&lt;span style="color:#f92672">&amp;amp;&lt;/span>p1, &lt;span style="color:#f92672">&amp;amp;&lt;/span>base, &lt;span style="color:#66d9ef">sizeof&lt;/span>(Entity));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;After memcpy: &amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Print(&lt;span style="color:#f92672">&amp;amp;&lt;/span>p1); &lt;span style="color:#75715e">// 这次，它一定会输出 I am Entity！
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="内存错位">内存错位&lt;a class="anchor" href="#%e5%86%85%e5%ad%98%e9%94%99%e4%bd%8d">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;cstring&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">BaseA&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">111&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">BaseB&lt;/span> {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">int&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">222&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// Child 同时拥有 a 和 b，继承顺序决定内存顺序，这里先BaseA--&amp;gt;BaseB--&amp;gt;自己的成员
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//在内存里，Child 对象是一块连续的砖，布局如下（假设每个 int 占 4 字节）：
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 字节偏移 内容 属于谁
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 0 int a(111) BaseA的地盘
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 4 int b(222) BaseB的地盘8int c(3)Child 的地盘
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Child&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">public&lt;/span> BaseA, &lt;span style="color:#66d9ef">public&lt;/span> BaseB {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">int&lt;/span> c &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">333&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> Child p;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> BaseB sourceB;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> sourceB.b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">999&lt;/span>; &lt;span style="color:#75715e">// 我们准备了一个新的 B，想把它拷进 p 里
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;--- 拷贝前 ---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;p.a = &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> p.a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; (BaseA部分)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;p.b = &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> p.b &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; (BaseB部分)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// --- 致命操作 ---
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 程序员的意图：把 sourceB 的数据拷贝给 p
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 程序员认为：p 既然继承了 BaseB，那我就直接拷过去
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>memcpy(&lt;span style="color:#f92672">&amp;amp;&lt;/span>p, &lt;span style="color:#f92672">&amp;amp;&lt;/span>sourceB, &lt;span style="color:#66d9ef">sizeof&lt;/span>(BaseB));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">--- 运行 memcpy(&amp;amp;p, &amp;amp;sourceB, ...) 后 ---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 错位发生了！
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 1. p.a 被改成了 999。因为 memcpy 从 p 的开头（BaseA的位置）开始写。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 2. p.b 依然是 222。因为它在内存后面，memcpy 根本没写到它。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;p.a = &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> p.a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; (被错误覆盖了！)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;p.b = &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> p.b &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34; (完全没被拷进去！)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>44复制和复制构造函数</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/44%E5%A4%8D%E5%88%B6%E5%92%8C%E5%A4%8D%E5%88%B6%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0/</link><pubDate>Wed, 14 Jan 2026 21:56:11 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/44%E5%A4%8D%E5%88%B6%E5%92%8C%E5%A4%8D%E5%88%B6%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0/</guid><description>&lt;p>了解在C++中复制的实际运作方式，以及如何让它工作，如何避免它工作（&lt;mark>避免在不想复制时复制，因为复制对性能有影响，有时只想读取对象或者修改现有对象&lt;/mark>）&lt;/p>
&lt;p>当你把变量赋值给另一个变量时，都是在使用复制。如果是指针，则是复制指针的地址（一串数字，而不是指针指向的内容）&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> b1 &lt;span style="color:#f92672">=&lt;/span> a1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//a，b是两个不同的变量，互不影响
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	b1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> b1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 a &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">2&lt;/span>,&lt;span style="color:#ae81ff">3&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 b &lt;span style="color:#f92672">=&lt;/span> a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	b.x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> a.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> b.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2&lt;span style="color:#f92672">*&lt;/span> aP &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Vector2();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//复制了指针，没有复制实际数据，复制的是地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Vector2&lt;span style="color:#f92672">*&lt;/span> bP &lt;span style="color:#f92672">=&lt;/span> aP;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	bP&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> aP&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> bP&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	bP&lt;span style="color:#f92672">++&lt;/span>;&lt;span style="color:#75715e">//aP没有被影响到
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> aP &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//000002A2946D9EC0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> bP &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//000002A2946D9EC8
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>除了引用以外，其他的给变量赋值，都是使用的复制&lt;/p></description></item><item><title>43智能指针</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/43%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/</link><pubDate>Mon, 12 Jan 2026 22:13:59 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/43%E6%99%BA%E8%83%BD%E6%8C%87%E9%92%88/</guid><description>&lt;p>智能指针，是真实原始指针被包装。使用智能指针时，将调用new并分配给你内存，这块内存在某些时候会自动释放&lt;/p>
&lt;h1 id="unique-pointer-唯一指针">unique pointer 唯一指针&lt;a class="anchor" href="#unique-pointer-%e5%94%af%e4%b8%80%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;p>在一个作用域内，同一个原始指针只能被一个 unique_ptr 管理。它禁止拷贝，这意味着你不能通过赋值来增加它的引用，只能使用 &lt;code>std::move()&lt;/code> 将所有权从一个指针转移给另一个。&lt;/p>
&lt;h2 id="转让所有权-附加知识点">转让所有权-附加知识点&lt;a class="anchor" href="#%e8%bd%ac%e8%ae%a9%e6%89%80%e6%9c%89%e6%9d%83-%e9%99%84%e5%8a%a0%e7%9f%a5%e8%af%86%e7%82%b9">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span> {};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 1. 创建第一个 unique_ptr
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> entity &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>make_unique&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 2. 使用 std::move 转移所有权
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#75715e">// 此时，entity 原有的内存所有权交给了 e2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> e2 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(entity);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">// 3. 检查状态
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span> &lt;span style="color:#66d9ef">if&lt;/span> (entity &lt;span style="color:#f92672">==&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;entity 现在是空的 (nullptr)&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">if&lt;/span> (e2 &lt;span style="color:#f92672">!=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;e2 现在拥有 Entity 的所有权&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} &lt;span style="color:#75715e">// e2 在这里离开作用域，Entity 被自动销毁
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="示例-主要知识点">示例-主要知识点&lt;a class="anchor" href="#%e7%a4%ba%e4%be%8b-%e4%b8%bb%e8%a6%81%e7%9f%a5%e8%af%86%e7%82%b9">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;memory&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//constructor-构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Created Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//destructor-析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#f92672">~&lt;/span>Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroyed Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hello&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;start--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不允许，禁止隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//std::unique_ptr&amp;lt;Entity&amp;gt; entity =new Entity();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//允许,直接调用构造函数，但是不建议
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//如果创建完原始对象后发生了异常，没有来得及将它放到智能指针对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//会导致不释放指针指向内存，导致内存泄漏
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//std::unique_ptr&amp;lt;Entity&amp;gt; entity(new Entity());
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//不会有这问题，因为std::make_unique保证了创建对象和将其
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 放入智能指针是一个原子操作==，中间不会被其他逻辑插入，因
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">// 此它是异常安全的。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> entity &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>make_unique&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span>();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		entity&lt;span style="color:#f92672">-&amp;gt;&lt;/span>Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>unique_ptr&lt;span style="color:#f92672">&amp;lt;&lt;/span>Entity&lt;span style="color:#f92672">&amp;gt;&lt;/span> e2 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>move(entity);&lt;span style="color:#75715e">//允许
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//std::unique_ptr&amp;lt;Entity&amp;gt; e3 = entity;//不允许，编译报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">/*查看源码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">		* 复制构造函数和赋值操作符被删除
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">			unique_ptr(const unique_ptr&amp;amp;) = delete;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">			unique_ptr&amp;amp; operator=(const unique_ptr&amp;amp;) = delete;		
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">		*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;end--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">start--
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">hello
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">end--
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>不允许&lt;code>std::unique_ptr&amp;lt;Entity&amp;gt; entity =new Entity();&lt;/code> 因为禁止隐式转换&lt;/p></description></item><item><title>42对象生命周期</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/42%E5%AF%B9%E8%B1%A1%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</link><pubDate>Mon, 12 Jan 2026 17:33:52 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/42%E5%AF%B9%E8%B1%A1%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F/</guid><description>&lt;p>栈中对象的生命周期&lt;/p>
&lt;h1 id="范围">范围&lt;a class="anchor" href="#%e8%8c%83%e5%9b%b4">#&lt;/a>&lt;/h1>
&lt;h2 id="栈">栈&lt;a class="anchor" href="#%e6%a0%88">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//constructor-构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Created Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//destructor-析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#f92672">~&lt;/span>Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroyed Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;start--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Entity e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;end--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">start--
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">end--
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>超出范围则自动销毁&lt;/p>
&lt;h2 id="堆">堆&lt;a class="anchor" href="#%e5%a0%86">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//constructor-构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Created Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//destructor-析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#f92672">~&lt;/span>Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroyed Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;start--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Entity&lt;span style="color:#f92672">*&lt;/span> e&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#66d9ef">new&lt;/span> Entity();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;end--&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">start--
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">end--
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="返回栈内存的指针及解决办法">返回栈内存的指针及解决办法&lt;a class="anchor" href="#%e8%bf%94%e5%9b%9e%e6%a0%88%e5%86%85%e5%ad%98%e7%9a%84%e6%8c%87%e9%92%88%e5%8f%8a%e8%a7%a3%e5%86%b3%e5%8a%9e%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//constructor-构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Created Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//destructor-析构函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#f92672">~&lt;/span>Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroyed Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">CreateArrayWrong&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在栈上声明一个数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//第一个元素为6，剩余49个为0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> array[&lt;span style="color:#ae81ff">50&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> { &lt;span style="color:#ae81ff">6&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//返回指向该数组(栈内存)的指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> array;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">CreateArray1&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在栈上声明一个数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//第一个元素为6，剩余49个为0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> array &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>] { &lt;span style="color:#ae81ff">6&lt;/span> };
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//返回指向该数组(栈内存)的指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">return&lt;/span> array;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">CreateArray2&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//填充数组
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//错误,这里得到的数据是不可信的，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//极有可能被其他代码拿来使用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> CreateArrayWrong();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//方法1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> a1 &lt;span style="color:#f92672">=&lt;/span> CreateArray1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//方法2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> array[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	CreateArray2(array);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="智能指针">智能指针&lt;a class="anchor" href="#%e6%99%ba%e8%83%bd%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;p>这是一个包装类，构造在栈中使用指针，分配堆内存；在包装类销毁时删除指针&lt;/p></description></item><item><title>41this关键字</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/41this%E5%85%B3%E9%94%AE%E5%AD%97/</link><pubDate>Sun, 11 Jan 2026 23:07:21 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/41this%E5%85%B3%E9%94%AE%E5%AD%97/</guid><description>&lt;p>this： 是一个指针，指向当前对象实例&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>;&lt;span style="color:#75715e">//必要的，视频没有加上
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity&lt;/span>(Entity&lt;span style="color:#f92672">*&lt;/span> e);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity2&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">&amp;amp;&lt;/span> e);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">int&lt;/span> x, &lt;span style="color:#66d9ef">int&lt;/span> y)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//这里会报错，this是指针常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//this = nullptr;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//this是指针常量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//这里如果不加const不会报错,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//视频教程中必须加否则报错，不知道为啥
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		Entity&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> e &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>; 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//或者//(*e).x = x;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		e&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>x &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">this&lt;/span>&lt;span style="color:#f92672">-&amp;gt;&lt;/span>y &lt;span style="color:#f92672">=&lt;/span> y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		PrintEntity(&lt;span style="color:#66d9ef">this&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		PrintEntity2(&lt;span style="color:#f92672">*&lt;/span>&lt;span style="color:#66d9ef">this&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">delete&lt;/span> e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetX&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//没有const修饰会报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//Entity* e = this;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">*&lt;/span> e &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">this&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity&lt;/span>(Entity&lt;span style="color:#f92672">*&lt;/span> e)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Print
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity2&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">&amp;amp;&lt;/span> e)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Print
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>40运算符和运算符重载</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/40%E8%BF%90%E7%AE%97%E7%AC%A6%E5%92%8C%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD/</link><pubDate>Sun, 11 Jan 2026 16:24:51 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/40%E8%BF%90%E7%AE%97%E7%AC%A6%E5%92%8C%E8%BF%90%E7%AE%97%E7%AC%A6%E9%87%8D%E8%BD%BD/</guid><description>&lt;h1 id="重载运算符">重载运算符&lt;code>+&lt;/code>&lt;a class="anchor" href="#%e9%87%8d%e8%bd%bd%e8%bf%90%e7%ae%97%e7%ac%a6">#&lt;/a>&lt;/h1>
&lt;h2 id="方法1">方法1&lt;a class="anchor" href="#%e6%96%b9%e6%b3%951">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>x(x), y(y) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Vector2(x &lt;span style="color:#f92672">+&lt;/span> other.x, y &lt;span style="color:#f92672">+&lt;/span> other.y);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">+&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Add&lt;/span>(other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#a6e22e">Multiply&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Vector2(x &lt;span style="color:#f92672">*&lt;/span> other.x, y &lt;span style="color:#f92672">*&lt;/span> other.y);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 position(&lt;span style="color:#ae81ff">4.0f&lt;/span>, &lt;span style="color:#ae81ff">4.0f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 speed(&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.5f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 powerup(&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.5f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 result1 &lt;span style="color:#f92672">=&lt;/span> position.Add(speed.Multiply(powerup));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 result2 &lt;span style="color:#f92672">=&lt;/span> position &lt;span style="color:#f92672">+&lt;/span> speed;&lt;span style="color:#75715e">// *powerup;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="方法2">方法2&lt;a class="anchor" href="#%e6%96%b9%e6%b3%952">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>x(x), y(y) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//this是指向自身的一个指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//return *this + other;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//或者
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">+&lt;/span>(other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">+&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>(x &lt;span style="color:#f92672">+&lt;/span> other.x, y &lt;span style="color:#f92672">+&lt;/span> other.y);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#a6e22e">Multiply&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Vector2(x &lt;span style="color:#f92672">*&lt;/span> other.x, y &lt;span style="color:#f92672">*&lt;/span> other.y);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 position(&lt;span style="color:#ae81ff">4.0f&lt;/span>, &lt;span style="color:#ae81ff">4.0f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 speed(&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.5f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 powerup(&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.5f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 result1 &lt;span style="color:#f92672">=&lt;/span> position.Add(speed.Multiply(powerup));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 result2 &lt;span style="color:#f92672">=&lt;/span> position &lt;span style="color:#f92672">+&lt;/span> speed;&lt;span style="color:#75715e">// *powerup;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="重载运算符--及-">重载运算符 &lt;code>*&lt;/code> 及 &lt;code>==&lt;/code>&lt;a class="anchor" href="#%e9%87%8d%e8%bd%bd%e8%bf%90%e7%ae%97%e7%ac%a6--%e5%8f%8a-">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">struct&lt;/span> &lt;span style="color:#a6e22e">Vector2&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>x(x), y(y) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#a6e22e">Add&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Vector2(x &lt;span style="color:#f92672">+&lt;/span> other.x, y &lt;span style="color:#f92672">+&lt;/span> other.y);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">+&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Add&lt;/span>(other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#a6e22e">Multiply&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> Vector2(x &lt;span style="color:#f92672">*&lt;/span> other.x, y &lt;span style="color:#f92672">*&lt;/span> other.y);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">*&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#a6e22e">Multiply&lt;/span>(other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">==&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> x &lt;span style="color:#f92672">==&lt;/span> other.x &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> y &lt;span style="color:#f92672">==&lt;/span> other.y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">bool&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">!=&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other) &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//return !(*this == other);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//或者
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> &lt;span style="color:#f92672">!&lt;/span>&lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">==&lt;/span>(other);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span>(std&lt;span style="color:#f92672">::&lt;/span>ostream&lt;span style="color:#f92672">&amp;amp;&lt;/span> stream, &lt;span style="color:#66d9ef">const&lt;/span> Vector2&lt;span style="color:#f92672">&amp;amp;&lt;/span> other)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	stream &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> other.x &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> other.y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> stream;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 position(&lt;span style="color:#ae81ff">4.0f&lt;/span>, &lt;span style="color:#ae81ff">4.0f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 speed(&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.5f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 powerup(&lt;span style="color:#ae81ff">0.5f&lt;/span>, &lt;span style="color:#ae81ff">1.5f&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 result1 &lt;span style="color:#f92672">=&lt;/span> position.Add(speed.Multiply(powerup));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Vector2 result2 &lt;span style="color:#f92672">=&lt;/span> position &lt;span style="color:#f92672">+&lt;/span> speed &lt;span style="color:#f92672">*&lt;/span> powerup; 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> result1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> result2 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (result1 &lt;span style="color:#f92672">==&lt;/span> result2)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;---equals---&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>运算符重载本质上就是函数。虽然你可以自定义运算符的行为（即函数体里写什么），但你不能改变 C++ 语言定义的运算符规则，包括：&lt;/p></description></item><item><title>39显式转换和隐式转换</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/39%E6%98%BE%E5%BC%8F%E8%BD%AC%E6%8D%A2%E5%92%8C%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2/</link><pubDate>Sun, 11 Jan 2026 14:56:35 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/39%E6%98%BE%E5%BC%8F%E8%BD%AC%E6%8D%A2%E5%92%8C%E9%9A%90%E5%BC%8F%E8%BD%AC%E6%8D%A2/</guid><description>&lt;p>隐式转换表示你没有明确告诉他你要这么做&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> m_Age;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//加上explicit则拒绝隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">/*explicit*/&lt;/span> Entity(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(name), m_Age(&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*explicit*/&lt;/span> Entity(&lt;span style="color:#66d9ef">int&lt;/span> age)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(&lt;span style="color:#e6db74">&amp;#34;Unknown&amp;#34;&lt;/span>), m_Age(age) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">&amp;amp;&lt;/span> entity)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//直接初始化，直接寻找匹配的构造函数，不属于隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity a(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity b(&lt;span style="color:#ae81ff">22&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//违反了“最多只能进行一次用户自定义转换”的原则
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//先从const char[7]转换为std::string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//然后从std::string转换为Entity
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Entity a1 = &amp;#34;Cherno&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//PrintEntity(&amp;#34;Cherno&amp;#34;);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity a1 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity b2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">22&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//建议这样书写简单明了
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Entity b3(22);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//隐式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	PrintEntity(&lt;span style="color:#ae81ff">22&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	PrintEntity(std&lt;span style="color:#f92672">::&lt;/span>string(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//只进行一次转换，把 const char[7]转换为std::string
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//这里没有涉及到把xx转换为Entity，所以即使
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// explicit Entity(const std::string&amp;amp; name)也
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//能编译通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	PrintEntity(Entity(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>));
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//强制显式转换
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity a3 &lt;span style="color:#f92672">=&lt;/span> (Entity)&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不转换而是直接调用构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity a3 &lt;span style="color:#f92672">=&lt;/span> Entity(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>38new关键字</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/38new%E5%85%B3%E9%94%AE%E5%AD%97/</link><pubDate>Sun, 11 Jan 2026 12:46:30 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/38new%E5%85%B3%E9%94%AE%E5%AD%97/</guid><description>&lt;h1 id="常见用法">常见用法&lt;a class="anchor" href="#%e5%b8%b8%e8%a7%81%e7%94%a8%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;code>new 指定数据类型&lt;/code>，数据类型包括类、原始类型、数组，根据数据类型确定必要的大小，以字节为单位&lt;/li>
&lt;li>&lt;code>new int&lt;/code>，4字节。向操作系统找到连续的4字节大小的内存，然后返回指向该内存地址的指针&lt;/li>
&lt;li>有一个空闲列表维护具体可用字节的地址，不需要一个个地址扫描是否可用&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//类型别名 (Type Alias) 声明。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">using&lt;/span> String &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity() &lt;span style="color:#f92672">:&lt;/span>m_Name(&lt;span style="color:#e6db74">&amp;#34;Unknown&amp;#34;&lt;/span>) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name) &lt;span style="color:#f92672">:&lt;/span>m_Name(name) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetName() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Name; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//连续的50个元素(200个字节)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> b_arr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> e1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Entity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//和上面那句一个意思
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity&lt;span style="color:#f92672">*&lt;/span> e2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Entity();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//为了在执行 delete[] e_arr 时知道要调用多少次析构函数，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 编译器通常会在分配的内存块头部额外存储一个计数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 器（Cookie），记录数组的长度。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//e_arr指向内存块的大小：50 * sizeof(Entity) + sizeof(size_t)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//size_t是 C++ 中专门用来表示内存大小和索引的类型:64位系统中是8字节，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//32位系统中是4字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//连续的50个Entity
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity&lt;span style="color:#f92672">*&lt;/span> e_arr &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> Entity[&lt;span style="color:#ae81ff">50&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>补充：&lt;code>new&lt;/code>，&lt;code>delete&lt;/code>，&lt;code>delete[]&lt;/code> 其实是一个运算符&lt;/p></description></item><item><title>37创建对象</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/37%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1/</link><pubDate>Sat, 10 Jan 2026 22:39:57 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/37%E5%88%9B%E5%BB%BA%E5%AF%B9%E8%B1%A1/</guid><description>&lt;p>两种方式，取决于我们在内存的哪个位置创建对象(堆heap或栈stack)&lt;/p>
&lt;p>C++ 有一条基本准则：任何不同的对象在内存中都必须有唯一的地址。所以如果创建了两个对象&lt;code>class Empty {};Empty e1;Empty e2;&lt;/code>，只有他们都有1字节大小的情况下，e1和e2才会有不同的内存地址&lt;/p>
&lt;ul>
&lt;li>栈上创建的对象，有自动的生命周期，由他们的作用域决定的，离开作用域则消失&lt;/li>
&lt;li>堆上创建的对象，会一直在，直到你手动释放它&lt;/li>
&lt;/ul>
&lt;h1 id="栈上创建对象">栈上创建对象&lt;a class="anchor" href="#%e6%a0%88%e4%b8%8a%e5%88%9b%e5%bb%ba%e5%af%b9%e8%b1%a1">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//类型别名 (Type Alias) 声明。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">using&lt;/span> String &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// using 声明，使用的时候只能用string(只起到了省略std::的作用)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//using std::string; 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">- 如果你把&amp;#34;using String = ... 还是 using std::string;&amp;#34;写
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">在 .h (头文件) 的全局作用域里，都会产生“污染”：
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">- 任何 #include 你这个头文件的人，都会被强制接受你的命名习惯。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">如果别人也定义了一个 String，代码就会崩溃（冲突）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	String m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity() &lt;span style="color:#f92672">:&lt;/span>m_Name(&lt;span style="color:#e6db74">&amp;#34;Unknown&amp;#34;&lt;/span>) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> name) &lt;span style="color:#f92672">:&lt;/span>m_Name(name) {}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> String&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetName() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Name; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Function&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity entity &lt;span style="color:#f92672">=&lt;/span> Entity(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Function();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity&lt;span style="color:#f92672">*&lt;/span> e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//在栈上创建对象（这里会默认调用默认构造函数）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		Entity entity3(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		e &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>entity3;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> e&lt;span style="color:#f92672">-&amp;gt;&lt;/span>GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在栈上创建对象（这里会默认调用默认构造函数）
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> entity.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在栈上创建对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity1(&lt;span style="color:#e6db74">&amp;#34;Cherno1&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> entity1.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//在栈上创建对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity entity2 &lt;span style="color:#f92672">=&lt;/span> Entity(&lt;span style="color:#e6db74">&amp;#34;Cherno2&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> entity2.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>在&lt;code>e = &amp;amp;entity3;&lt;/code>加断点，并走到下一步&lt;/p></description></item><item><title>36三元运算符</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/36%E4%B8%89%E5%85%83%E8%BF%90%E7%AE%97%E7%AC%A6/</link><pubDate>Sat, 10 Jan 2026 22:03:11 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/36%E4%B8%89%E5%85%83%E8%BF%90%E7%AE%97%E7%AC%A6/</guid><description>&lt;p>if-else的语法糖&lt;/p>
&lt;h1 id="初试">初试&lt;a class="anchor" href="#%e5%88%9d%e8%af%95">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> s_Level &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">12&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> s_Speed &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		s_Speed &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		s_Speed &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	s_Speed &lt;span style="color:#f92672">=&lt;/span> s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//嵌套
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//s_Level &amp;gt; 5 &amp;amp;&amp;amp; s_Level &amp;lt; 100 这个会先被连接在一起判断
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	s_Speed &lt;span style="color:#f92672">=&lt;/span> s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">&amp;amp;&amp;amp;&lt;/span> s_Level &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">100&lt;/span> &lt;span style="color:#f92672">?&lt;/span> s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#ae81ff">15&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果&amp;gt;5的情况下，如果还&amp;gt;10，则15，如果不大于10则10；否则(不
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//&amp;gt;5)，则5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	s_Speed &lt;span style="color:#f92672">=&lt;/span> s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span> &lt;span style="color:#f92672">?&lt;/span> s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#ae81ff">15&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//方式1：这里没有多构造空对象其实和编译器有关，后面会说到
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string rank &lt;span style="color:#f92672">=&lt;/span> s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span> &lt;span style="color:#f92672">?&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Master&amp;#34;&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Beginer&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//方式2：这种声明方式，还会比上面额外多构造一个空字符串对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string otherRank;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">if&lt;/span> (s_Level &lt;span style="color:#f92672">&amp;gt;&lt;/span> &lt;span style="color:#ae81ff">10&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		otherRank &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Master&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">else&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		otherRank &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Beginer&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> s_Speed &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl; &lt;span style="color:#75715e">//15
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="解释一下方式2">解释一下方式2&lt;a class="anchor" href="#%e8%a7%a3%e9%87%8a%e4%b8%80%e4%b8%8b%e6%96%b9%e5%bc%8f2">#&lt;/a>&lt;/h1>
&lt;p>编译器并不会先创建一个临时的 std::string 之后再拷贝给 rank。它的执行逻辑如下：&lt;/p></description></item><item><title>35成员变量初始化</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/35%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E5%88%9D%E5%A7%8B%E5%8C%96/</link><pubDate>Fri, 09 Jan 2026 23:24:46 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/35%E6%88%90%E5%91%98%E5%8F%98%E9%87%8F%E5%88%9D%E5%A7%8B%E5%8C%96/</guid><description>&lt;h1 id="普通的初始化方法">普通的初始化方法&lt;a class="anchor" href="#%e6%99%ae%e9%80%9a%e7%9a%84%e5%88%9d%e5%a7%8b%e5%8c%96%e6%96%b9%e6%b3%95">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span> &lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Unknown&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_Name &lt;span style="color:#f92672">=&lt;/span> name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetName() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Name; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e0;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> e0.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e1(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> e1.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="初始化列表">初始化列表&lt;a class="anchor" href="#%e5%88%9d%e5%a7%8b%e5%8c%96%e5%88%97%e8%a1%a8">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> m_Score;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果不是用初始化列表，就会先调用成员变量的构造函数初始化给它默认值(这里是m_Name)，然后在{}中再一次赋值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果用了，那就直接使用初始化列表中的值初始化
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//第二种方式只调用了string(const char*)，而第一种方式多调用了一次string()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span>m_Name(&lt;span style="color:#e6db74">&amp;#34;Unknown&amp;#34;&lt;/span>),m_Score(&lt;span style="color:#ae81ff">0&lt;/span>) &lt;span style="color:#75715e">//注意不论这里的书写顺序是啥
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//都是先初始化m_Score，再m_Name
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity(&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#f92672">:&lt;/span> m_Name(name)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetName() &lt;span style="color:#66d9ef">const&lt;/span> { &lt;span style="color:#66d9ef">return&lt;/span> m_Name; }
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e0;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> e0.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e1(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> e1.GetName() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="构造函数的幕后过程">构造函数的“幕后”过程&lt;a class="anchor" href="#%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0%e7%9a%84%e5%b9%95%e5%90%8e%e8%bf%87%e7%a8%8b">#&lt;/a>&lt;/h2>
&lt;blockquote class='book-hint '>
&lt;p>初始化阶段：以下只针对类对象，基本类型不会被自动初始化（除非是全局变量：全局变量会被清零），它们的值是内存中残留的随机垃圾值。&lt;/p></description></item><item><title>33-34const、mutable关键字</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/33-34constmutable%E5%85%B3%E9%94%AE%E5%AD%97/</link><pubDate>Sun, 04 Jan 2026 00:44:12 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/33-34constmutable%E5%85%B3%E9%94%AE%E5%AD%97/</guid><description>&lt;h1 id="常量折叠类型强转">常量折叠、类型强转&lt;a class="anchor" href="#%e5%b8%b8%e9%87%8f%e6%8a%98%e5%8f%a0%e7%b1%bb%e5%9e%8b%e5%bc%ba%e8%bd%ac">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//当你定义 const int MAX_AGE = 90; 时，编译器通常会进行常量折叠（Constant Folding）。这意味着在编译阶段，代码中所有出现 MAX_AGE 的地方都会被直接替换为数字 90;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//所以最下面的 std::cout &amp;lt;&amp;lt; MAX_AGE &amp;lt;&amp;lt; std::endl; 打印90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> MAX_AGE &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">90&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> MAX_AGE &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">*&lt;/span>a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果不加 (int*)类型强转,提示 a value of type &amp;#34;const int *&amp;#34;cannot beassigned to an entity of type &amp;#34;int *&amp;#34;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//报错原因：1. 如果你能直接把 const int* 赋值给 int*，那么你就可以通过 *a = 100; 来修改 MAX_AGE 的值。这违背了 const 的初衷。为了保证代码的健壮性，编译器禁止这种**“权限扩大”**的行为（从“只读”变成“可读写”）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	2. 为什么加上(int*) 就不报错了？
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	当你加上(int*) 时，你正在使用强制类型转换（C - style Cast）。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//	这相当于你对编译器说：“我知道 MAX_AGE 是常数，我也知道我在把只读指针转成可读写指针，出了问题我负责，请闭嘴。” 编译器接收到了你的强制指令，于是停止报错。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	a &lt;span style="color:#f92672">=&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">&amp;amp;&lt;/span>MAX_AGE;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#f92672">*&lt;/span>a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果MAX_AGE加了volatile关键字修饰，即	const volatile int MAX_AGE = 90;那
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//么不会发生常量折叠，这里应该打印的是5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> MAX_AGE &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//90
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//MAX_AGE 对应的内存空间，通过指针非法修改成了 5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="const的修饰位置">const的修饰位置&lt;a class="anchor" href="#const%e7%9a%84%e4%bf%ae%e9%a5%b0%e4%bd%8d%e7%bd%ae">#&lt;/a>&lt;/h1>
&lt;h2 id="变量中">变量中&lt;a class="anchor" href="#%e5%8f%98%e9%87%8f%e4%b8%ad">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> MAX_AGE &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">90&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不能修改指针指向的地址里的值(但可以修改指针指向)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//int const* a = new int;//跟上一句一个意思,const都是在*前面
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//*a = 2;//报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//由于a已经是const int*了，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//所以这里编译器没有像int* a时报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>MAX_AGE;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#f92672">*&lt;/span>a &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//90 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不能修改指针指向的地址里的值(但可以修改指针指向)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">*&lt;/span>b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>; &lt;span style="color:#75715e">//可修改地址里的值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不可重新分配b指向其他地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//b = &amp;amp;MAX_AGE;//报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> c &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> d &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*以下均编译不通过*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//*c = 2;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//c = &amp;amp;MAX_AGE;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//*d = 2;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//d = &amp;amp;MAX_AGE;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">/*以上均编译不通过*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="class中">class中&lt;a class="anchor" href="#class%e4%b8%ad">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> m_X, m_Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> s_X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> m_XP;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//const: 在该方法中不允许修改成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//禁止修改成员变量： 在该函数内部，你不能对任何非 static 成员变量进行赋值操作。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//禁止调用非 const 函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> GetX() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//m_X = 3;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		s_X &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//test();//会报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> m_X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//返回一个int指针，且该指针不能改变所存地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//指向的值，也不能指向其他地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#a6e22e">GetXP&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_XP;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">test&lt;/span>() &lt;span style="color:#75715e">//const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="形参中">形参中&lt;a class="anchor" href="#%e5%bd%a2%e5%8f%82%e4%b8%ad">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> m_X, m_Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> m_X1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">mutable&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> var;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> GetX1() 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_X1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">GetX&lt;/span>() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//var是一个mutable变量,在const方法中可以修改它
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		var &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">return&lt;/span> m_X;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">SetX&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> x)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_X &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity1&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">*&lt;/span> e)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	e &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">nullptr&lt;/span>;&lt;span style="color:#75715e">//允许编译，允许指向其他
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//(*e).SetX(2);//报错，不允许修改值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> (&lt;span style="color:#f92672">*&lt;/span>e).GetX() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintEntity2&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> Entity&lt;span style="color:#f92672">&amp;amp;&lt;/span> e)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//e = nullptr;//不允许编译，因为是引用，不允许重新指向其他
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//e.SetX(2);//报错，不允许修改值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> e.GetX() &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不允许调用非const修饰的函数，下面会报错,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//因为无法保证GetX1()是否修改了e，而e是const修饰的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::cout &amp;lt;&amp;lt; e.GetX1() &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="mutable">mutable&lt;a class="anchor" href="#mutable">#&lt;/a>&lt;/h1>
&lt;h2 id="class成员变量">class成员变量&lt;a class="anchor" href="#class%e6%88%90%e5%91%98%e5%8f%98%e9%87%8f">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//允许标记为const的方法修改该变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">mutable&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> m_DebugCount &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//1.如果是 const std::string，则返回的是一个副本
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//返回一个引用
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//2.最后的const表示该函数内部不允许修改类的非static成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string&lt;span style="color:#f92672">&amp;amp;&lt;/span> GetName() &lt;span style="color:#66d9ef">const&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//m_Name = &amp;#34;a&amp;#34;;//非法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		m_DebugCount&lt;span style="color:#f92672">++&lt;/span>;&lt;span style="color:#75715e">//编译通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//由于返回的是引用，所以这里返回了成员变
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//量 m_Name 的一个“地址”或“别名”
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">return&lt;/span> m_Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">MyTest&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> Entity e;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	e.GetName();&lt;span style="color:#75715e">//调用const方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//e.MyTest();//不允许调用非const方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e1;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	e1.GetName();&lt;span style="color:#75715e">//调用const方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	e1.MyTest();&lt;span style="color:#75715e">//调用非const方法 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="lambda表达式中">lambda表达式中&lt;a class="anchor" href="#lambda%e8%a1%a8%e8%be%be%e5%bc%8f%e4%b8%ad">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//lamda表达式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> z &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//按引用捕获所有变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> f1 &lt;span style="color:#f92672">=&lt;/span> [&lt;span style="color:#f92672">&amp;amp;&lt;/span>]()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;&lt;span style="color:#75715e">//合法,和原变量一样
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			&lt;span style="color:#75715e">//z = 5;//不合法,和原变量一样是const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//mutable 不能直接修饰普通的局部变量或全局变量,只能
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//是类成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//mutable int m2 = 0;//没这种写法，会报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//按值捕获所有变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> f2 &lt;span style="color:#f92672">=&lt;/span> [&lt;span style="color:#f92672">=&lt;/span>]()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//y = 3;//不合法,默认是const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//按值捕获所有变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//默认情况下，Lambda 内部的 operator() 是 const 的，不允
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//许修改捕获的副本。加上 mutable 后，Lambda 内部就可以修改这些副本了。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> f2_1 &lt;span style="color:#f92672">=&lt;/span> [&lt;span style="color:#f92672">=&lt;/span>]() &lt;span style="color:#66d9ef">mutable&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">3&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Lambda 内部 y = &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;外部原变量 y = &amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//8
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//按值捕获x变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">auto&lt;/span> f3 &lt;span style="color:#f92672">=&lt;/span> [x]()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			&lt;span style="color:#75715e">//y = 3;//不合法,默认是const
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	f1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	f2();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	f3();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>字符串字面量</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/32%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AD%97%E9%9D%A2%E9%87%8F/</link><pubDate>Thu, 01 Jan 2026 19:26:44 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/32%E5%AD%97%E7%AC%A6%E4%B8%B2%E5%AD%97%E9%9D%A2%E9%87%8F/</guid><description>&lt;p>特殊情况&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;stdlib.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//(const char [7])&amp;#34;Cherno&amp;#34;，7字节，因为末尾有一个空字符&amp;#39;\0&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cher&lt;/span>&lt;span style="color:#ae81ff">\0&lt;/span>&lt;span style="color:#e6db74">no&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//Cher
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span> name[&lt;span style="color:#ae81ff">8&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Che&lt;/span>&lt;span style="color:#ae81ff">\0&lt;/span>&lt;span style="color:#e6db74">rno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="img/ly-20260102194456478.png" alt="" />&lt;/p>
&lt;h1 id="注意事项">注意事项&lt;a class="anchor" href="#%e6%b3%a8%e6%84%8f%e4%ba%8b%e9%a1%b9">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;stdlib.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//(const char [7])&amp;#34;Cherno&amp;#34;，7字节，因为末尾有一个空字符&amp;#39;\0&amp;#39;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cher&lt;/span>&lt;span style="color:#ae81ff">\0&lt;/span>&lt;span style="color:#e6db74">no&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//Cher
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span> name[&lt;span style="color:#ae81ff">8&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Che&lt;/span>&lt;span style="color:#ae81ff">\0&lt;/span>&lt;span style="color:#e6db74">rno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> strlen(name) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//3,不把\0算在内
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/* 错误的，某些编译器允许编译通过,但没效果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	char* name1 = &amp;#34;Cherno&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	name1[2] = &amp;#39;a&amp;#39;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	std::cout &amp;lt;&amp;lt; name1 &amp;lt;&amp;lt; std::endl;//Cherno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//一定要修改的话
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">char&lt;/span> name2[] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	name2[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;a&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> name2 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//Charno
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="不同类型的字符串">不同类型的字符串&lt;a class="anchor" href="#%e4%b8%8d%e5%90%8c%e7%b1%bb%e5%9e%8b%e7%9a%84%e5%ad%97%e7%ac%a6%e4%b8%b2">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name_ &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">u8&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//字符串中的每个字符都是宽字符（wchar_t 类型）,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//通常是16位或32位，取决于系统(大小平台相关)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//L 前缀表示这是一个宽字符字符串
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">wchar_t&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">L&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// C++11后的UTF-16字符串,固定每个字符2字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char16_t&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name3 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">u&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// C++11后的UTF-32字符串,固定每个字符4字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char32_t&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name4 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">U&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="字面量运算符">字面量运算符&lt;a class="anchor" href="#%e5%ad%97%e9%9d%a2%e9%87%8f%e8%bf%90%e7%ae%97%e7%ac%a6">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//&amp;#34;&amp;#34; 是字面量运算符名称的一部分
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//它表示这个运算符处理的是字符串字面量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//其他类型的字面量有不同的前缀：
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">// 不同的字面量类型有不同的运算符名称：
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>std&lt;span style="color:#f92672">::&lt;/span>string &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>s(...); &lt;span style="color:#75715e">// 字符串字面量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">long&lt;/span> &lt;span style="color:#66d9ef">double&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>ld(...); &lt;span style="color:#75715e">// 浮点数字面量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">long&lt;/span> &lt;span style="color:#66d9ef">long&lt;/span> &lt;span style="color:#66d9ef">operator&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&amp;#34;&lt;/span>ull(...); &lt;span style="color:#75715e">// 整数型字面量
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;string&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;stdlib.h&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//启用了 &amp;#34;text&amp;#34;s 语法，让创建 std::string 对象更加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 直观、类型安全，特别是在自动类型推导和复杂字符串场景下非常有用。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">using&lt;/span> &lt;span style="color:#66d9ef">namespace&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string_literals;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::string name0 = &amp;#34;Cherno&amp;#34; + &amp;#34; hello&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string name0 &lt;span style="color:#f92672">=&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>string(&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>) &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34; hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//// 普通运算符重载：没有引号
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::string operator+(const std::string &amp;amp; a, const std::string &amp;amp; b);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 字面量运算符：必须有 &amp;#34;&amp;#34; 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//std::string operator&amp;#34;&amp;#34;s(const char* str, size_t len);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//std::string operator&amp;#34;&amp;#34;s(const char* str, size_t len);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//下面的语句,相当于std::string name1 = operator&amp;#34;&amp;#34;s(&amp;#34;Cherno&amp;#34;, 6) + &amp;#34; hello&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>string name1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>s &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34; hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> name1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>string name2 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">u8&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>s &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">&amp;#34; hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>wstring name3 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">L&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>s &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">L&lt;/span>&lt;span style="color:#e6db74">&amp;#34; hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>u32string name4 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">U&lt;/span>&lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>s &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#e6db74">U&lt;/span>&lt;span style="color:#e6db74">&amp;#34; hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//R 表示 Raw string literal（原始字符串字面量），括号内的内容会完全按照原样被存储，包括换行符、制表符等特殊字符。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> example &lt;span style="color:#f92672">=&lt;/span> R&lt;span style="color:#e6db74">&amp;#34;(Line1&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Line2
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Line3
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>Line4)&lt;span style="color:#e6db74">&amp;#34;;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Line1
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Line2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Line3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Line4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> example1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Line1&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#e6db74">&amp;#34;Line2&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#e6db74">&amp;#34;Line3&lt;/span>&lt;span style="color:#ae81ff">\n&lt;/span>&lt;span style="color:#e6db74">&amp;#34;&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#e6db74">&amp;#34;Line4&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example1 &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="查看字面量汇编文件">查看字面量汇编文件&lt;a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e5%ad%97%e9%9d%a2%e9%87%8f%e6%b1%87%e7%bc%96%e6%96%87%e4%bb%b6">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span> name[] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	name[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;a&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> name &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="img/ly-20260104004004867.png" alt="" />&lt;/p></description></item><item><title>31字符串</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/31%E5%AD%97%E7%AC%A6%E4%B8%B2/</link><pubDate>Thu, 01 Jan 2026 18:04:34 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/31%E5%AD%97%E7%AC%A6%E4%B8%B2/</guid><description>&lt;ul>
&lt;li>字符串本质上是&lt;mark>一组字符(字符数组)&lt;/mark>，字符，即数字、字母等等&lt;/li>
&lt;li>需要在计算机上以某种形式表示文本&lt;/li>
&lt;li>如果想要在C++中实现字符串功能，先要了解字符的工作原理，以及字符是什么。&lt;/li>
&lt;li>如果我们只用一个字节(8位)来表示一个字符，那么就有2&lt;sup>8=256种可能性。但是如果考虑到字母、数字、特殊符号、中文、韩文远超过256种。所以后面才有16字符编码(UTF-16) &lt;del>UTF-16通常使用16位（2字节）编码一个基本字符&lt;/del> (65536种可能性，一开始是2字节，2&lt;/sup>16 = 65536，后面发现65536不够用，进行了扩展，一个字符可能占：2字节或4字节，也成UTF-16。 &lt;del>UTF-32特制固定用4字节表示一个字符的字符编码&lt;/del> )。&lt;/li>
&lt;li>实际上 C++ 可以处理：ASCII，UTF-8，UTF-16，UTF-32。取决于：编译器，源文件编码，字符类型，字符串类型&lt;/li>
&lt;/ul>
&lt;p>本章节中，其实字符串指的是字符指针&lt;/p>
&lt;h1 id="字符串修改问题">字符串修改问题&lt;a class="anchor" href="#%e5%ad%97%e7%ac%a6%e4%b8%b2%e4%bf%ae%e6%94%b9%e9%97%ae%e9%a2%98">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//C风格的定义字符串的方式
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//char* name = &amp;#34;Cherno&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//正常情况下不修改字符串的值,
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//如果想要新的字符串，那么就要进行全新
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//的内存分配并删除旧字符串(这里不是new，不
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//需要手动delete)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name1 &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Cherno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//const在*前面，不允许修改数据
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//name[2] = &amp;#39;1&amp;#39;;//报错!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//name1[2] = &amp;#39;1&amp;#39;;//报错!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span> buffer[] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#66d9ef">const&lt;/span> ptr &lt;span style="color:#f92672">=&lt;/span> buffer;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//const在*后面，不允许指向另一个字符串
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//ptr = new char[3] {&amp;#39;a&amp;#39;,&amp;#39;b&amp;#39;,&amp;#39;c&amp;#39;};//报错!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="字符串在内存中">字符串在内存中&lt;a class="anchor" href="#%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%9c%a8%e5%86%85%e5%ad%98%e4%b8%ad">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20260102145214909.png" alt="" />&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//关闭编译器的安全检查来强制通过下一行代码
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//项目-属性-c++-语言:符合模式--&amp;gt;否,宽松模式。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// 编译器会允许一些非标准或旧版本 C++ 的写法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//char* name = &amp;#34;Charno&amp;#34;;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//ASCII码: 43 68 61 72 6E 6F 00
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Charno&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	name &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#66d9ef">new&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>[&lt;span style="color:#ae81ff">3&lt;/span>] {&lt;span style="color:#e6db74">&amp;#39;a&amp;#39;&lt;/span>, &lt;span style="color:#e6db74">&amp;#39;b&amp;#39;&lt;/span>,&lt;span style="color:#e6db74">&amp;#39;\0&amp;#39;&lt;/span>};&lt;span style="color:#75715e">//允许
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//name[2] = &amp;#39;a&amp;#39;; //不允许
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> name &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="字符串的基本原理">字符串的基本原理&lt;a class="anchor" href="#%e5%ad%97%e7%ac%a6%e4%b8%b2%e7%9a%84%e5%9f%ba%e6%9c%ac%e5%8e%9f%e7%90%86">#&lt;/a>&lt;/h1>
&lt;p>字符串在内存中&lt;/p></description></item><item><title>30数组</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/30%E6%95%B0%E7%BB%84/</link><pubDate>Thu, 01 Jan 2026 10:40:02 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/30%E6%95%B0%E7%BB%84/</guid><description>&lt;p>数组：一个集合，一堆元素按照特定的顺序排列起来&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> example[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//无效值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example[&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//编译器不检查越界
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example[&lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example[&lt;span style="color:#ae81ff">5&lt;/span>] &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//数组内存地址
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> example &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">2
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-858993460
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-858993460
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">-858993460
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0000006DC77EFB38
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="循环">循环&lt;a class="anchor" href="#%e5%be%aa%e7%8e%af">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> example[&lt;span style="color:#ae81ff">5&lt;/span>];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">0&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">1&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">2&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">3&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">4&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	example[&lt;span style="color:#ae81ff">4&lt;/span>] &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		example[i] &lt;span style="color:#f92672">=&lt;/span> i;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如果，数组在内存中是连续的同类型数值 ~~小端法， 这里&lt;mark>1个&lt;/mark>int占用4字节，在内存中按最低有效字节到最高有效字节顺序在内存中排列 ~~&lt;br>
&lt;img src="img/ly-20260101124624766.png" alt="" />&lt;/p></description></item><item><title>26-29继承_虚函数_接口_可见性</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/26-29%E7%BB%A7%E6%89%BF_%E8%99%9A%E5%87%BD%E6%95%B0_%E6%8E%A5%E5%8F%A3_%E5%8F%AF%E8%A7%81%E6%80%A7/</link><pubDate>Wed, 31 Dec 2025 18:12:27 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/26-29%E7%BB%A7%E6%89%BF_%E8%99%9A%E5%87%BD%E6%95%B0_%E6%8E%A5%E5%8F%A3_%E5%8F%AF%E8%A7%81%E6%80%A7/</guid><description>&lt;h1 id="继承">继承&lt;a class="anchor" href="#%e7%bb%a7%e6%89%bf">#&lt;/a>&lt;/h1>
&lt;h2 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> X, Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Move&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span> xa, &lt;span style="color:#66d9ef">float&lt;/span> ya)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		X &lt;span style="color:#f92672">+=&lt;/span> xa;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Y &lt;span style="color:#f92672">+=&lt;/span> ya;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//public表示子类继承的父类的成员变量/方法，
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//最高只能是public。如果是class Player :protected Entity
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//则原来父类中的public成员变量变成protected，但是原来的protected
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//和private成员变量则不变
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Player&lt;/span> &lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#66d9ef">public&lt;/span> Entity
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> Name;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">PrintName&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> Name &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//64位系统，Entity两个float，占用了16字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">float&lt;/span>) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//4
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(&lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span>) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//8
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(Entity) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//4+4=8
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#66d9ef">sizeof&lt;/span>(Player) &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;span style="color:#75715e">//4+4+8=16
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Player player;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.Move(&lt;span style="color:#ae81ff">5&lt;/span>, &lt;span style="color:#ae81ff">5&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.X &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>多态：如果我现在创建一个独立的函数来打印Entity对象，例如通过访问X和Y变量并将它们打印出来。那我其实也可以将Player对象传递给该函数&lt;/p></description></item><item><title>24-25构造函数和析构函数</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/24-25%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%92%8C%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0/</link><pubDate>Wed, 31 Dec 2025 15:31:53 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/24-25%E6%9E%84%E9%80%A0%E5%87%BD%E6%95%B0%E5%92%8C%E6%9E%90%E6%9E%84%E5%87%BD%E6%95%B0/</guid><description>&lt;h1 id="构造函数">构造函数&lt;a class="anchor" href="#%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0">#&lt;/a>&lt;/h1>
&lt;p>我们每次实例化一个对象时都会运行的一个特殊函数&lt;/p>
&lt;h2 id="例子">例子&lt;a class="anchor" href="#%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP24
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{ 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//C++中不处理的话默认不初始化任何成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">float&lt;/span> X, Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//默认的构造函数，什么都不做
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不写任何构造函数是会默认添加这个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Entity()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		X &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.00f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.00f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Created Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//带参数的构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		X &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Y &lt;span style="color:#f92672">=&lt;/span> y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroyed Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> X &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> Y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Function&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//声明了一个函数：	函数名：e1，	返回类型：Entity，参数：无
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity e1();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e;&lt;span style="color:#75715e">//栈上分配
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity e2{};&lt;span style="color:#75715e">//栈上分配
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	e.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Function();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0,0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="不希望其他人使用构造函数">不希望其他人使用构造函数&lt;a class="anchor" href="#%e4%b8%8d%e5%b8%8c%e6%9c%9b%e5%85%b6%e4%bb%96%e4%ba%ba%e4%bd%bf%e7%94%a8%e6%9e%84%e9%80%a0%e5%87%bd%e6%95%b0">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Log&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Log()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//或者
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	Log() = delete;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">static&lt;/span> &lt;span style="color:#66d9ef">void&lt;/span> Write()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Log l;&lt;span style="color:#75715e">//这里会报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="析构函数">析构函数&lt;a class="anchor" href="#%e6%9e%90%e6%9e%84%e5%87%bd%e6%95%b0">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>当你摧毁一个对象时，会调用析构函数，析构函数主要用来清楚任何不再需要的内存&lt;/li>
&lt;li>最典型的例子，如果在构造对象时在堆上分配内存，则必须在析构函数中手动清理它&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Entity&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//C++中不处理的话默认不初始化任何成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">float&lt;/span> X, Y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//默认的构造函数，什么都不做
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不写任何构造函数是会默认添加这个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//Entity()
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//{
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//}
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		X &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.00f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0.00f&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Created Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//带参数的构造函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Entity(&lt;span style="color:#66d9ef">float&lt;/span> x, &lt;span style="color:#66d9ef">float&lt;/span> y) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		X &lt;span style="color:#f92672">=&lt;/span> x;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Y &lt;span style="color:#f92672">=&lt;/span> y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#f92672">~&lt;/span>Entity()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Destroyed Entity!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Print&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> X &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;,&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> Y &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Function&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Entity e;&lt;span style="color:#75715e">//栈上分配
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	e.Print();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Function();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> &lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Created Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">0,0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">Destroyed Entity!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e"> */&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>23enum</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/23enum/</link><pubDate>Tue, 30 Dec 2025 22:17:14 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/23enum/</guid><description>&lt;ul>
&lt;li>枚举，其实就是&lt;mark>一组&lt;/mark>值&lt;/li>
&lt;li>想用整数 &lt;del>只能是整数，比如char，signed char，unsigned char，short，unsigned short，int，unsigned int，long，unsigned long，long long，unsigned long long，不能是浮点类型&lt;/del> 来表示某些状态，并且给他们命名&lt;/li>
&lt;li>这里解释一下char为什么分 char 和 signed char：&lt;mark>signed char 明确表示 -128&lt;sub>127 的小整数；unsigned char 明确表示 0&lt;/sub>255；char 是专门给字符用的类型，它的符号性由编译器决定。&lt;/mark>&lt;/li>
&lt;li>&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#ifdef LY_EP23
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//默认情况下是无符号整型unsigned int
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">Example&lt;/span>&lt;span style="color:#f92672">:&lt;/span>&lt;span style="color:#66d9ef">unsigned&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果不指定的话，第一个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//为0，然后逐个增加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//只要没有指定的值，都会根据前一个指定的值逐个增加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	A,B,C
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">e_MyLong&lt;/span> &lt;span style="color:#f92672">:&lt;/span> &lt;span style="color:#66d9ef">long&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//如果不指定的话，第一个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//为0，然后逐个增加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//只要没有指定的值，都会根据前一个指定的值逐个增加
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	A1, B1, C1
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> c &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Example value &lt;span style="color:#f92672">=&lt;/span> B;&lt;span style="color:#75715e">//如果e_MyLong里面也有B的话，编译器会报错
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Example value1 &lt;span style="color:#f92672">=&lt;/span> Example&lt;span style="color:#f92672">::&lt;/span>B;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//if (value == 1) //也可以这么写
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">if&lt;/span> (value &lt;span style="color:#f92672">==&lt;/span> B) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;get&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#endif&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="日志系统改进">日志系统改进&lt;a class="anchor" href="#%e6%97%a5%e5%bf%97%e7%b3%bb%e7%bb%9f%e6%94%b9%e8%bf%9b">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Log&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">enum&lt;/span> &lt;span style="color:#a6e22e">Level&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//这里不能用Error，因为下面有一个同名函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		LevelError&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>, LevelWarning, LevelInfo
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}; 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//日志实际级别
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//m开头表示类成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Level m_LogLevel &lt;span style="color:#f92672">=&lt;/span> LevelInfo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> SetLevel(Level level)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_LogLevel &lt;span style="color:#f92672">=&lt;/span> level;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//关于字符串指针，后面会讲解
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Error&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#75715e">//因为枚举类型是整型，所以
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#75715e">//这里可以比较
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_LogLevel &lt;span style="color:#f92672">&amp;gt;=&lt;/span> LevelError)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[ERROR]:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Warn&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_LogLevel &lt;span style="color:#f92672">&amp;gt;=&lt;/span> LevelWarning)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[WARNING]:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Info&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_LogLevel &lt;span style="color:#f92672">&amp;gt;=&lt;/span> LevelInfo)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[INFO]:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Log log;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//警告或更严重的消息会被打印出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	log.SetLevel(Log&lt;span style="color:#f92672">::&lt;/span>LevelWarning);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	log.Warn(&lt;span style="color:#e6db74">&amp;#34;Hello!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	log.Error(&lt;span style="color:#e6db74">&amp;#34;Hello!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	log.Info(&lt;span style="color:#e6db74">&amp;#34;Hello!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	[WARNING]:Hello!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	[ERROR]:Hello!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div></description></item><item><title>20-22面向对象</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/20-22%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</link><pubDate>Tue, 30 Dec 2025 14:45:25 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/20-22%E9%9D%A2%E5%90%91%E5%AF%B9%E8%B1%A1/</guid><description>&lt;h1 id="编写一个类">编写一个类&lt;a class="anchor" href="#%e7%bc%96%e5%86%99%e4%b8%80%e4%b8%aa%e7%b1%bb">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Log&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> LogLevelError &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> LogLevelWarning &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">int&lt;/span> LogLevelInfo &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">private&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//日志实际级别
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//m开头表示类成员变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> m_LogLevel &lt;span style="color:#f92672">=&lt;/span> LogLevelInfo;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> SetLevel(&lt;span style="color:#66d9ef">int&lt;/span> level)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		m_LogLevel &lt;span style="color:#f92672">=&lt;/span> level;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//关于字符串指针，后面会讲解
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Error&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_LogLevel &lt;span style="color:#f92672">&amp;gt;=&lt;/span> LogLevelError)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[ERROR]:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Warn&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_LogLevel &lt;span style="color:#f92672">&amp;gt;=&lt;/span> LogLevelWarning)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[WARNING]:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Info&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (m_LogLevel &lt;span style="color:#f92672">&amp;gt;=&lt;/span> LogLevelInfo)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;[INFO]:&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> message &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Log log;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//警告或更严重的消息会被打印出
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	log.SetLevel(log.LogLevelWarning);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	log.Warn(&lt;span style="color:#e6db74">&amp;#34;Hello!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	log.Error(&lt;span style="color:#e6db74">&amp;#34;Hello!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	log.Info(&lt;span style="color:#e6db74">&amp;#34;Hello!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">/*
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	[WARNING]:Hello!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	[ERROR]:Hello!
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">	*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="静态_static">静态_static&lt;a class="anchor" href="#%e9%9d%99%e6%80%81_static">#&lt;/a>&lt;/h1>
&lt;p>使用场景：类/结构体内部；类/结构体外部&lt;/p></description></item><item><title>18-19类_基础</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/18-19%E7%B1%BB_%E5%9F%BA%E7%A1%80/</link><pubDate>Tue, 30 Dec 2025 00:08:25 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/18-19%E7%B1%BB_%E5%9F%BA%E7%A1%80/</guid><description>&lt;h1 id="类_基础知识">类_基础知识&lt;a class="anchor" href="#%e7%b1%bb_%e5%9f%ba%e7%a1%80%e7%9f%a5%e8%af%86">#&lt;/a>&lt;/h1>
&lt;p>类：将数据和功能整合在一起&lt;/p>
&lt;h2 id="类定义及函数">类定义及函数&lt;a class="anchor" href="#%e7%b1%bb%e5%ae%9a%e4%b9%89%e5%8f%8a%e5%87%bd%e6%95%b0">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//类定义
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Player&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//默认是私有的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//int x, y;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//这里的public包括了speed这个成员
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> speed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Move&lt;/span>(Player&lt;span style="color:#f92672">&amp;amp;&lt;/span> player, &lt;span style="color:#66d9ef">int&lt;/span> xa, &lt;span style="color:#66d9ef">int&lt;/span> ya)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.x &lt;span style="color:#f92672">+=&lt;/span> xa&lt;span style="color:#f92672">*&lt;/span>player.speed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.y &lt;span style="color:#f92672">+=&lt;/span> ya&lt;span style="color:#f92672">*&lt;/span>player.speed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//player:对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//创建(实例化)一个对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Player player;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.speed &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Move(player, &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(player.x);&lt;span style="color:#75715e">//3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	LOG(player.y);&lt;span style="color:#75715e">//0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="类定义及方法">类定义及方法&lt;a class="anchor" href="#%e7%b1%bb%e5%ae%9a%e4%b9%89%e5%8f%8a%e6%96%b9%e6%b3%95">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//类定义
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">class&lt;/span> &lt;span style="color:#a6e22e">Player&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//默认是私有的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//int x, y;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//这里的public包括了speed和Move这个成员
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">public&lt;/span>&lt;span style="color:#f92672">:&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> x, y;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> speed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//方法
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Move&lt;/span>( &lt;span style="color:#66d9ef">int&lt;/span> xa, &lt;span style="color:#66d9ef">int&lt;/span> ya)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		x &lt;span style="color:#f92672">+=&lt;/span> xa &lt;span style="color:#f92672">*&lt;/span> speed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		y &lt;span style="color:#f92672">+=&lt;/span> ya &lt;span style="color:#f92672">*&lt;/span> speed;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>};
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//player:对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//创建(实例化)一个对象
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	Player player;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.x &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.y &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.speed &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	player.Move( &lt;span style="color:#ae81ff">1&lt;/span>, &lt;span style="color:#f92672">-&lt;/span>&lt;span style="color:#ae81ff">1&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(player.x);&lt;span style="color:#75715e">//3
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	LOG(player.y);&lt;span style="color:#75715e">//0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="c中结构和类的区别">C++中结构和类的区别&lt;a class="anchor" href="#c%e4%b8%ad%e7%bb%93%e6%9e%84%e5%92%8c%e7%b1%bb%e7%9a%84%e5%8c%ba%e5%88%ab">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>
&lt;p>类的默认成员是私有的&lt;/p></description></item><item><title>17引用</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/17%E5%BC%95%E7%94%A8/</link><pubDate>Mon, 29 Dec 2025 22:13:50 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/17%E5%BC%95%E7%94%A8/</guid><description>&lt;blockquote class='book-hint '>
&lt;p>需要有pointer(指针)，即上一个视频的基础&lt;/p>&lt;/blockquote>&lt;blockquote class='book-hint '>
&lt;p>引用其实是指针的扩展，只是指向指针的语法糖，让他更容易阅读。引用本质上是引用现有变量，不同于指针，你可以在其中创建新的指针变量让后将其设置为空指针或其他。引用本身实际上并不占据新变量，他们实际上没有存储空间。&lt;/p>&lt;/blockquote>&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#f92672">&amp;amp;&lt;/span>a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//&amp;amp;符号是类型的一部分
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//使用ref就跟使用a的别名一样
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> ref &lt;span style="color:#f92672">=&lt;/span> a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//这里编译器编译后会直接设置a，而
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不会再创建一个变量
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ref &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">2&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(a); &lt;span style="color:#75715e">//5
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="使用地址增加">使用地址增加&lt;a class="anchor" href="#%e4%bd%bf%e7%94%a8%e5%9c%b0%e5%9d%80%e5%a2%9e%e5%8a%a0">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Increment&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> value) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//首先引用指针，然后增加指针处的值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	(&lt;span style="color:#f92672">*&lt;/span>value)&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Increment(&lt;span style="color:#f92672">&amp;amp;&lt;/span>a);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(a);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>使用引用实现一样的效果，但是代码更加美观&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Increment&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	value&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Increment(a);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(a);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="引用的禁忌">引用的禁忌&lt;a class="anchor" href="#%e5%bc%95%e7%94%a8%e7%9a%84%e7%a6%81%e5%bf%8c">#&lt;/a>&lt;/h1>
&lt;p>不能指向其他地方&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">void&lt;/span> &lt;span style="color:#a6e22e">Increment&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> value) { 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	value&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>()
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> b &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//必须初始化，否则编译错误
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">&amp;amp;&lt;/span> ref &lt;span style="color:#f92672">=&lt;/span> a;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//不会出现编译错误，但是其实没有任何效果
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	ref &lt;span style="color:#f92672">=&lt;/span> b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Increment(ref);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	LOG(b);&lt;span style="color:#75715e">//打印8，未改变b的值
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>指针，则可以任意变换赋值&lt;/p></description></item><item><title>16指针</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/16%E6%8C%87%E9%92%88/</link><pubDate>Tue, 23 Dec 2025 12:38:06 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/16%E6%8C%87%E9%92%88/</guid><description>&lt;p>&lt;em>&lt;strong>指针&lt;/strong>&lt;/em>&lt;/p>
&lt;p>当你写一个程序的时候，你启动他，整个应用程序就会加载到内存，告诉计算机根据代码执行的操作都被加载到内存中，这是cpu实际访问你写的变量的方式。&lt;/p>
&lt;p>指针，是一个==存储&lt;code>内存地址&lt;/code> &lt;del>表示内存地址&lt;/del> ==的&lt;em>数字&lt;/em>&lt;/p>
&lt;p>我们需要从内存中，读取或者写入东西，指针，就是内存的地址&lt;/p>
&lt;p>&lt;mark>忘记指针的类型&lt;/mark>&lt;/p>
&lt;h1 id="例子1-无类型指针">例子1-无类型指针&lt;a class="anchor" href="#%e4%be%8b%e5%ad%901-%e6%97%a0%e7%b1%bb%e5%9e%8b%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;p>&lt;code>void*&lt;/code> 表示我们不关心地址指向的实际数据是什么类型的&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#define LOG(x) std::cout &amp;lt;&amp;lt; x &amp;lt;&amp;lt; std::endl
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>(){
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">void&lt;/span>&lt;span style="color:#f92672">*&lt;/span> ptr&lt;span style="color:#f92672">=&lt;/span>&lt;span style="color:#ae81ff">0&lt;/span>;&lt;span style="color:#75715e">//0，表示这是一个无效指针
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//void* ptr=NULL;// NULL是一个# define NULL 0，其实也是0
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//void* ptr=nullptr;// c++11引入的
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>~~C/C++ 允许&lt;mark>局部函数声明&lt;/mark> ~~&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>void func(int);
void func(void*);
func(0);//调用func(int)，而不是 func(void*)，存在歧义
func(nullptr);// 明确调用 func(void*)&lt;/p>&lt;/blockquote>&lt;h1 id="例子2-类型指针">例子2-类型指针&lt;a class="anchor" href="#%e4%be%8b%e5%ad%902-%e7%b1%bb%e5%9e%8b%e6%8c%87%e9%92%88">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> var &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//void* ptr = &amp;amp;var;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	 &lt;span style="color:#66d9ef">int&lt;/span>&lt;span style="color:#f92672">*&lt;/span> ptr&lt;span style="color:#f92672">=&amp;amp;&lt;/span>var;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	 &lt;span style="color:#66d9ef">double&lt;/span>&lt;span style="color:#f92672">*&lt;/span> ptr1&lt;span style="color:#f92672">=&lt;/span>(&lt;span style="color:#66d9ef">double&lt;/span>&lt;span style="color:#f92672">*&lt;/span>)&lt;span style="color:#f92672">&amp;amp;&lt;/span>ptr; &lt;span style="color:#75715e">//我知道 ptr 是一个 int* 类型变量(一串表示地址的数字)，但我骗编译器说：ptr 这块内存里放的是一个 double。 骗编译器说 ptr 这个变量里面存放的那几个字节（也就是一个地址值）可以当成 double 来读取。
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//double* ptr=(double*)&amp;amp;var;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>调试查看ptr地址上的值&lt;/p></description></item><item><title>14-15循环</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/14-15%E5%BE%AA%E7%8E%AF/</link><pubDate>Sat, 20 Dec 2025 18:55:20 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/14-15%E5%BE%AA%E7%8E%AF/</guid><description>&lt;p>&lt;em>&lt;strong>循环&lt;/strong>&lt;/em>&lt;/p>
&lt;h1 id="for">for&lt;a class="anchor" href="#for">#&lt;/a>&lt;/h1>
&lt;p>当需要执行某些操作多次时&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i &lt;span style="color:#f92672">=&lt;/span> i &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Log(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ol>
&lt;li>先创建变量i(为零)&lt;/li>
&lt;li>然后检查i&amp;lt;5，是的话执行下面代码块(否则退出)&lt;/li>
&lt;li>然后i=i+1&lt;/li>
&lt;li>然后再检查i&amp;lt;5，是的话执行下面代码块(否则退出)&lt;/li>
&lt;li>3-&amp;gt;4-&amp;gt;3-&amp;gt;4 反复循环直到退出&lt;/li>
&lt;/ol>
&lt;blockquote class='book-hint '>
&lt;p>i的作用域仅限于for代码块&lt;/p>
&lt;p>&lt;img src="img/ly-20251221112821557.png" alt="" />&lt;/p>&lt;/blockquote>&lt;p>上述代码也可改为&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; ) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Log(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		i &lt;span style="color:#f92672">=&lt;/span> i &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>或者&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">bool&lt;/span> condition &lt;span style="color:#f92672">=&lt;/span> true;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (; condition; ) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Log(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		i &lt;span style="color:#f92672">=&lt;/span> i &lt;span style="color:#f92672">+&lt;/span> &lt;span style="color:#ae81ff">1&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">if&lt;/span> (&lt;span style="color:#f92672">!&lt;/span>(i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>))
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>			condition &lt;span style="color:#f92672">=&lt;/span> false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>死循环&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">for&lt;/span>(;;)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="while">while&lt;a class="anchor" href="#while">#&lt;/a>&lt;/h1>
&lt;p>基本上可以和for语句互转。但是如果有已经存在的条件，优先使用while&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">while&lt;/span> (i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		Log(&lt;span style="color:#e6db74">&amp;#34;Hello World&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		i&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="do-while">do while&lt;a class="anchor" href="#do-while">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//执行前先判断
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">bool&lt;/span> condition &lt;span style="color:#f92672">=&lt;/span> false;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">while&lt;/span> (condition)
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//至少执行一次
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">do&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>{
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>} &lt;span style="color:#66d9ef">while&lt;/span> (condition);&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="控制流">控制流&lt;a class="anchor" href="#%e6%8e%a7%e5%88%b6%e6%b5%81">#&lt;/a>&lt;/h1>
&lt;p>continue，break（如果有多重循环，不会影响到外部的循环）&lt;/p></description></item><item><title>13vs用于c++项目的最佳实践</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/13vs%E7%94%A8%E4%BA%8Ec++%E9%A1%B9%E7%9B%AE%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</link><pubDate>Sat, 20 Dec 2025 16:08:08 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/13vs%E7%94%A8%E4%BA%8Ec++%E9%A1%B9%E7%9B%AE%E7%9A%84%E6%9C%80%E4%BD%B3%E5%AE%9E%E8%B7%B5/</guid><description>&lt;p>&lt;em>&lt;strong>vs用于c++项目的最佳实践&lt;/strong>&lt;/em>&lt;/p>
&lt;h1 id="创建新项目">创建新项目&lt;a class="anchor" href="#%e5%88%9b%e5%bb%ba%e6%96%b0%e9%a1%b9%e7%9b%ae">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20251220171552364.png" alt="" />&lt;/p>
&lt;p>解决方案下有项目&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>MySolusion.sln是解决方案文件&lt;/p>&lt;/blockquote>&lt;p>&lt;img src="img/ly-20251220171512084.png" alt="" />&lt;/p>
&lt;p>项目下是源代码&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>Project.vcxproj 是项目相关文件
Project.vcxproj.filters 是过滤器&lt;/p>&lt;/blockquote>&lt;p>&lt;img src="img/ly-20251220171638015.png" alt="" />&lt;/p>
&lt;p>过滤器决定了vs IDE打开该项目时的视图(实际中不存在文件夹)&lt;/p>
&lt;p>&lt;img src="img/ly-20251220172459926.png" alt="" />&lt;/p>
&lt;h1 id="显示所有文件">显示所有文件&lt;a class="anchor" href="#%e6%98%be%e7%a4%ba%e6%89%80%e6%9c%89%e6%96%87%e4%bb%b6">#&lt;/a>&lt;/h1>
&lt;p>显示磁盘目录下的所有文件&lt;/p>
&lt;p>&lt;img src="img/ly-20251220180714438.png" alt="" />&lt;/p>
&lt;p>移动文件位置&lt;/p>
&lt;p>&lt;img src="img/ly-20251220182103808.png" alt="" />&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello World!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>如图，中间文件(.obj)是放在项目文件夹里&lt;/p>
&lt;p>&lt;img src="img/ly-20251220182411767.png" alt="" />&lt;/p>
&lt;p>项目编译后生成的可执行文件放在（总的）解决方案文件夹下&lt;/p>
&lt;p>&lt;img src="img/ly-20251220182451084.png" alt="" />&lt;/p>
&lt;p>由来&lt;/p>
&lt;p>&lt;img src="img/ly-20251220182725107.png" alt="" />&lt;/p>
&lt;p>&lt;code>$(Platform)\$(Configuration)\&lt;/code>，即 &lt;code>x64\Debug&lt;/code> 文件夹结构的由来&lt;/p>
&lt;h1 id="修改配置">修改配置&lt;a class="anchor" href="#%e4%bf%ae%e6%94%b9%e9%85%8d%e7%bd%ae">#&lt;/a>&lt;/h1>
&lt;p>OutputDirectory: &lt;code>$(SolutionDir)bin\$(Platform)\$(Configuration)\&lt;/code>&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>如果解决方案有多个项目，如果构建DLL文件或者其他需要的东西，我们需要这些在同一个文件夹中（而不用深入每个项目的文件夹）&lt;/p>&lt;/blockquote>&lt;p>IntermediateDirectory: &lt;code>$(SolutionDir)bin\intermediates\$(Platform)\$(Configuration)\&lt;/code>&lt;/p>
&lt;p>&lt;del>这里建议加上项目名，避免中间文件冲突(覆盖) &lt;code>$(SolutionDir)bin\intermediates\$(ProjectName)\$(Platform)\$(Configuration)\&lt;/code>&lt;/del>&lt;/p>
&lt;p>&lt;img src="img/ly-20251220185019820.png" alt="" />&lt;/p>
&lt;p>之后右键项目-clean Solution&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>查看变量值&lt;/p>
&lt;p>&lt;img src="img/ly-20251220185324170.png" alt="" />
&lt;img src="img/ly-20251220185302696.png" alt="" />&lt;/p>&lt;/blockquote>&lt;h2 id="清理项目">清理项目&lt;a class="anchor" href="#%e6%b8%85%e7%90%86%e9%a1%b9%e7%9b%ae">#&lt;/a>&lt;/h2>
&lt;p>解决方案下有一个项目&lt;/p>
&lt;p>&lt;img src="img/ly-20251220184230313.png" alt="" />&lt;/p></description></item><item><title>12条件及分支</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/12%E6%9D%A1%E4%BB%B6%E5%8F%8A%E5%88%86%E6%94%AF/</link><pubDate>Fri, 19 Dec 2025 00:22:47 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/12%E6%9D%A1%E4%BB%B6%E5%8F%8A%E5%88%86%E6%94%AF/</guid><description>&lt;p>&lt;em>&lt;strong>条件及分支&lt;/strong>&lt;/em>&lt;/p>
&lt;ul>
&lt;li>先检查一个条件，然后跳转到不同的部分并开始执行指令，意味着条件及分支都有会一点开销。如果想编写稍微快点的代码就不该使用条件语句&lt;/li>
&lt;li>如果某事是真的，那么跳转到对应的代码块执行&lt;/li>
&lt;/ul>
&lt;h1 id="查看汇编">查看汇编&lt;a class="anchor" href="#%e6%9f%a5%e7%9c%8b%e6%b1%87%e7%bc%96">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20251219181756962.png" alt="" />&lt;/p>
&lt;p>&lt;img src="img/ly-20251219181921962.png" alt="" />&lt;/p>
&lt;ul>
&lt;li>
&lt;p>&lt;code>mov dword ptr [x],6&lt;/code>&lt;mark>意思是&lt;/mark>&lt;code>在内存中名为 x 的位置，写入4个字节的数值 00000006（十六进制）&lt;/code>&lt;/p>
&lt;ul>
&lt;li>mov:移动&lt;/li>
&lt;li>cmp 比较&lt;/li>
&lt;li>jne:是否为零&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>
&lt;p>不相等则跳转&lt;br>
&lt;img src="img/ly-20251219225117649.png" alt="" />&lt;/p>
&lt;/li>
&lt;li>
&lt;p>并且将某个位置（代表变量comparisionResult设置为0）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>其中，&lt;code>dword ptr [rbp+0F4h],0 &lt;/code> 表示 &lt;code>将0存储到内存地址rbp+0xF4处的4字节空间（双字）中&lt;/code> ，rbp通常指基指针寄存器（Base Pointer Register），通常是栈帧的基地址&lt;/p>
&lt;/li>
&lt;li>
&lt;p>test基本是执行 &lt;code>按位与&lt;/code> 运算&lt;br>
&lt;img src="img/ly-20251219231053130.png" alt="" />&lt;/p>
&lt;blockquote class='book-hint '>
&lt;p>补充：test eax, eax 不会改变 eax 的值，只是临时计算 eax AND eax，然后丢弃结果，唯一目的：设置CPU的标志位 &lt;del>同时，test 指令还会强制清零 溢出标志（OF = 0）和进位标志（CF = 0）&lt;/del>
为什么要自己和自己AND？因为 eax AND eax 的结果就是 eax 本身：如果 eax = 0 → 结果是 0 → ZF=1 &lt;del>零标志位（ZF, Zero Flag）&lt;/del> ；如果 eax ≠ 0 → 结果非零 → ZF=0 ；如果 eax &amp;lt; 0（最高位为1） → SF=1 &lt;del>符号标志位（SF, Sign Flag）&lt;/del>&lt;/p></description></item><item><title>11如何调试代码</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/11%E5%A6%82%E4%BD%95%E8%B0%83%E8%AF%95%E4%BB%A3%E7%A0%81/</link><pubDate>Wed, 17 Dec 2025 23:17:36 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/11%E5%A6%82%E4%BD%95%E8%B0%83%E8%AF%95%E4%BB%A3%E7%A0%81/</guid><description>&lt;p>&lt;em>&lt;strong>如何调试代码&lt;/strong>&lt;/em>&lt;/p>
&lt;ul>
&lt;li>断点&lt;/li>
&lt;li>读取内存&lt;/li>
&lt;/ul>
&lt;ol>
&lt;li>
&lt;p>光标放到要调试的行，然后鼠标移动到最前面点一下/或者按F9，即可在该行插入断点&lt;/p>
&lt;/li>
&lt;li>
&lt;p>确保是Debug模式，而且点击&lt;code>LocalWindowsDebugger&lt;/code>&lt;br>
&lt;img src="img/ly-20251217233251059.png" alt="" />&lt;/p>
&lt;/li>
&lt;li>
&lt;p>调试中&lt;br>
&lt;img src="img/ly-20251217233813020.png" alt="" />
橘黄色指向指令指针目前的位置
stepInto(F11):进入目前行所在函数&lt;/p>
&lt;p>stepOver(F10):继续执行到下一行&lt;/p>
&lt;p>stepOut(shift+F11)：跳出当前函数&lt;/p>
&lt;/li>
&lt;/ol>
&lt;p>此时按F11进入函数(这里和视频不太一样，黄色箭头在左括号处是读不到数值的)&lt;/p>
&lt;p>&lt;img src="img/ly-20251217234537606.png" alt="" />&lt;/p>
&lt;p>再按一次F10执行到第一行代码前才行&lt;/p>
&lt;p>&lt;img src="img/ly-20251217234702002.png" alt="" />&lt;/p>
&lt;p>再按一次F10&lt;/p>
&lt;p>&lt;img src="img/ly-20251217234823363.png" alt="" />&lt;/p>
&lt;p>再按一次F10就继续执行（这里会跳出Log函数）&lt;/p>
&lt;p>按F5会继续执行，直到下一个断点&lt;/p>
&lt;h1 id="调试">调试&lt;a class="anchor" href="#%e8%b0%83%e8%af%95">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;iostream&amp;#34;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;Log.h&amp;#34;&lt;/span>&lt;span style="color:#75715e"> 
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//InitLog();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#66d9ef">int&lt;/span> a &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	a&lt;span style="color:#f92672">++&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> string &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#34;Hello&amp;#34;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">for&lt;/span> (&lt;span style="color:#66d9ef">int&lt;/span> i &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">0&lt;/span>; i &lt;span style="color:#f92672">&amp;lt;&lt;/span> &lt;span style="color:#ae81ff">5&lt;/span>; i&lt;span style="color:#f92672">++&lt;/span>) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span> c &lt;span style="color:#f92672">=&lt;/span> string[i];
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>		std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> c &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Log(&lt;span style="color:#e6db74">&amp;#34;hello world!&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//std::cin.get();
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>&lt;img src="img/ly-20251218224343475.png" alt="" />&lt;br>
箭头在此处，表示该行代码即将执行（未执行），所以此时a为任意可能值(未初始化的内存)&lt;/p>
&lt;p>Autos(ide认为比较重要的)，Locals(本地变量)，Watch1(自己添加的监视器)&lt;/p>
&lt;ul>
&lt;li>显示所有的程序内存&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="img/ly-20251218224949957.png" alt="" />&lt;/p>
&lt;ul>
&lt;li>左边是内存地址，右边是实际数据&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="img/ly-20251218225333366.png" alt="" />&lt;/p>
&lt;ul>
&lt;li>Memory中查看变量值(这里1个int变量占用&lt;mark>4个字节&lt;/mark>)&lt;/li>
&lt;/ul>
&lt;p>&lt;img src="img/ly-20251219000641173.png" alt="" />&lt;/p></description></item><item><title>08-10变量、函数</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/08-10%E5%8F%98%E9%87%8F%E5%87%BD%E6%95%B0/</link><pubDate>Mon, 15 Dec 2025 14:17:30 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/08-10%E5%8F%98%E9%87%8F%E5%87%BD%E6%95%B0/</guid><description>&lt;h1 id="变量">变量&lt;a class="anchor" href="#%e5%8f%98%e9%87%8f">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>&lt;mark>编程实际上就是在操纵数据&lt;/mark>&lt;/li>
&lt;li>变量允许我们&lt;mark>命名一个我们存储在内存中的数据&lt;/mark>&lt;/li>
&lt;li>我们创建的变量存储在堆栈或堆中&lt;/li>
&lt;li>原始数据是构成任何种类的基石&lt;/li>
&lt;li>不同的变量类型，唯一的区别，是存储他们需要多少内存(原始数据类型有多大)&lt;/li>
&lt;/ul>
&lt;h2 id="整数">整数&lt;a class="anchor" href="#%e6%95%b4%e6%95%b0">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> variable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">8&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> variable &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	variable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">20&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> variable &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;ul>
&lt;li>int变量通常上是4字节，取决于编译器&lt;/li>
&lt;li>可以不用立即赋值&lt;/li>
&lt;li>大概在-20亿~+20亿之间&lt;/li>
&lt;li>4字节是32位，int是有符号的，第32位存储符号位。还剩下31位存储数据。2^31=21 4748 3648 。
&lt;ul>
&lt;li>最大正数：2^31-1=21 4748 3647&lt;/li>
&lt;li>最小负数：-(2^31)=-21 4748 3648&lt;/li>
&lt;li>为什么负数多一个，因为多了一个&amp;quot;-0&amp;quot;但int中没有-0的 &lt;del>浮点数中有-0.0的概念&lt;/del> 概念，二进制10000000 00000000 00000000 00000000 代表-(2^31)&lt;/li>
&lt;/ul>
&lt;/li>
&lt;li>unsint 表示无符号整数，能用上所有的位，即最大整数是(2^32) -1&lt;/li>
&lt;li>其他：char 1字节，short 2字节，int 4字节，long 通常4字节，long long 通常8字节 &lt;del>由于32位系统最大是4字节，所以long也是4字节。后来出了64位系统，64位windows系统中long是4字节，64位Linux/macOS中long是8字节&lt;/del> 可以给任何一个前面加unsigned表示无符号&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">char&lt;/span> cVariable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;A&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//char cVariable=65;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不管是用65还是&amp;#39;A&amp;#39;赋值，打印出来的都是A
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> cVariable &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">short&lt;/span> sVariable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#e6db74">&amp;#39;A&amp;#39;&lt;/span>;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//short cVariable=65;
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//不管是用65还是&amp;#39;A&amp;#39;赋值，打印出来的都是65
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> sVariable &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="小数">小数&lt;a class="anchor" href="#%e5%b0%8f%e6%95%b0">#&lt;/a>&lt;/h2>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-cpp" data-lang="cpp">&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">float&lt;/span> fVariable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">8.2f&lt;/span>;&lt;span style="color:#75715e">//4字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> fVariable &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">double&lt;/span> dVariable &lt;span style="color:#f92672">=&lt;/span> &lt;span style="color:#ae81ff">20.3&lt;/span>;&lt;span style="color:#75715e">//8字节
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> dVariable &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h2 id="布尔值">布尔值&lt;a class="anchor" href="#%e5%b8%83%e5%b0%94%e5%80%bc">#&lt;/a>&lt;/h2>
&lt;p>布尔类型只占用1个字节（只需要1位，但我们在处理内存寻址时，即我们要从那里取回我们的值时，或者将它存储在内存体重时，没有办法只处理个别位，所以只能按字节取）&lt;/p></description></item><item><title>07链接器</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/07%E9%93%BE%E6%8E%A5%E5%99%A8/</link><pubDate>Sat, 13 Dec 2025 17:12:49 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/07%E9%93%BE%E6%8E%A5%E5%99%A8/</guid><description>&lt;p>&lt;em>&lt;strong>07链接器&lt;/strong>&lt;/em>&lt;/p>
&lt;h1 id="介绍">介绍&lt;a class="anchor" href="#%e4%bb%8b%e7%bb%8d">#&lt;/a>&lt;/h1>
&lt;p>编译器将C++ 源文件编译成.obj目标文件后，需要进行&lt;mark>链接&lt;/mark>：&lt;mark>找到每个符号和函数的位置并将它们链接在一起&lt;/mark>，在这之前每个文件都已经被编译成了一个单独的目标文件作为翻译单元，它们彼此之间没有任何联系&lt;/p>
&lt;p>Ctrl+F7只会编译文件，不会将文件链接；build项目会链接文件。&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c++" data-lang="c++">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> &lt;span style="color:#a6e22e">Log&lt;/span>(&lt;span style="color:#66d9ef">const&lt;/span> &lt;span style="color:#66d9ef">char&lt;/span>&lt;span style="color:#f92672">*&lt;/span> message) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> message;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">Multiply&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> a,&lt;span style="color:#66d9ef">int&lt;/span> b ) { 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	Log(&lt;span style="color:#e6db74">&amp;#34;Multiply&amp;#34;&lt;/span>);
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> a &lt;span style="color:#f92672">*&lt;/span> b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>编译实际上分为编译和链接两个阶段。如果上面代码去掉一个分号，则出现错误&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>1&amp;gt;E:&lt;span style="color:#ae81ff">\c&lt;/span>ppStudyTemp&lt;span style="color:#ae81ff">\C&lt;/span>hernoCpp&lt;span style="color:#ae81ff">\H&lt;/span>elloWorld01&lt;span style="color:#ae81ff">\H&lt;/span>elloWorld01&lt;span style="color:#ae81ff">\M&lt;/span>ath.cpp&lt;span style="color:#f92672">(&lt;/span>10,1&lt;span style="color:#f92672">)&lt;/span>: error 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>C2143: syntax error: missing &lt;span style="color:#e6db74">&amp;#39;;&amp;#39;&lt;/span> before &lt;span style="color:#e6db74">&amp;#39;}&amp;#39;&lt;/span> 
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1&amp;gt;Done building project &lt;span style="color:#e6db74">&amp;#34;HelloWorld01.vcxproj&amp;#34;&lt;/span> -- FAILED.
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">==========&lt;/span> Build: &lt;span style="color:#ae81ff">0&lt;/span> succeeded, &lt;span style="color:#ae81ff">1&lt;/span> failed, &lt;span style="color:#ae81ff">0&lt;/span> up-to-date, &lt;span style="color:#ae81ff">0&lt;/span> skipped &lt;span style="color:#f92672">==========&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#f92672">==========&lt;/span> Build completed at 17:51 and took 05.115 seconds &lt;span style="color:#f92672">==========&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这里C2143，&lt;mark>C开头表示是编译阶段的错误&lt;/mark>&lt;/p>
&lt;p>补上后将整个项目build构建后，出现另一个错误：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-shell" data-lang="shell">&lt;span style="display:flex;">&lt;span>1&amp;gt;MSVCRTD.lib&lt;span style="color:#f92672">(&lt;/span>exe_main.obj&lt;span style="color:#f92672">)&lt;/span> : error LNK2019: unresolved external symbol main referenced in &lt;span style="color:#66d9ef">function&lt;/span> &lt;span style="color:#e6db74">&amp;#34;int __cdecl invoke_main(void)&amp;#34;&lt;/span> &lt;span style="color:#f92672">(&lt;/span>?invoke_main@@YAHXZ&lt;span style="color:#f92672">)&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1&amp;gt;E:&lt;span style="color:#ae81ff">\c&lt;/span>ppStudyTemp&lt;span style="color:#ae81ff">\C&lt;/span>hernoCpp&lt;span style="color:#ae81ff">\H&lt;/span>elloWorld01&lt;span style="color:#ae81ff">\x&lt;/span>64&lt;span style="color:#ae81ff">\D&lt;/span>ebug&lt;span style="color:#ae81ff">\H&lt;/span>elloWorld01.exe : fatal error LNK1120: &lt;span style="color:#ae81ff">1&lt;/span> unresolved externals
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>1&amp;gt;Done building project &lt;span style="color:#e6db74">&amp;#34;HelloWorld01.vcxproj&amp;#34;&lt;/span> -- FAILED.&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>这里出现LNK1120，&lt;mark>LNK开头表示链接阶段出现错误&lt;/mark>&lt;/p></description></item><item><title>06编译器</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/06%E7%BC%96%E8%AF%91%E5%99%A8/</link><pubDate>Sat, 13 Dec 2025 01:06:00 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/06%E7%BC%96%E8%AF%91%E5%99%A8/</guid><description>&lt;p>&lt;em>&lt;strong>编译器的工作原理&lt;/strong>&lt;/em>&lt;/p>
&lt;h1 id="介绍">介绍&lt;a class="anchor" href="#%e4%bb%8b%e7%bb%8d">#&lt;/a>&lt;/h1>
&lt;blockquote class='book-hint '>
&lt;p>源文件 &lt;em>编译&amp;ndash;&amp;gt;&lt;/em> .obj文件 &lt;em>链接&amp;ndash;&amp;gt;&lt;/em> .exe可执行文件&lt;/p>&lt;/blockquote>&lt;ul>
&lt;li>预处理(包括标记) &amp;ndash;&amp;gt; 创建一棵抽象语法树(将所有代码转换为常量数据或指令) &amp;ndash;&amp;gt; 创建代码(CPU将执行的实际机器码) &lt;del>这个有点抽象，其实就是处理代码的过程：源代码从“纯文本”蜕变为“结构化逻辑”，最终落实为“硬件机器指令”的编译全流程&lt;/del>&lt;/li>
&lt;li>编译器：为每个C++文件（先经过预处理成为翻译单元）生成&lt;em>目标文件&lt;/em>&lt;/li>
&lt;li>文件只是C++向编译器提供源代码的方式（并不需要像java那样文件名必须和类名等同）&lt;/li>
&lt;li>将.cpp当做C++文件，把.c当做C文件，把.h当做头文件。(默认，也可以改变这个默认约定)&lt;/li>
&lt;li>C++文件先经过预处理后成为翻译单元，之后编译器将翻译单元生成为一个目标文件，有时将CPP文件包含在其他CPP文件中并创建一个包含大量文件的大CPP文件。这种情况下只需要编译这个大的CPP文件并生成一个翻译单元，从而生成一个目标文件&lt;/li>
&lt;/ul>
&lt;h1 id="hash-include">hash include&lt;a class="anchor" href="#hash-include">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c++" data-lang="c++">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Math.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">Multiply&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> a, &lt;span style="color:#66d9ef">int&lt;/span> b) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> result &lt;span style="color:#f92672">=&lt;/span> a &lt;span style="color:#f92672">*&lt;/span> b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>并编译&lt;/p>
&lt;p>再添加一个文件&lt;mark>EndBrace.h&lt;/mark>&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c++" data-lang="c++">&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>修改Math.cpp，修改前删除结束括号，会编译出错，之后修改为：&lt;/p>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c++" data-lang="c++">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//Math.cpp
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">Multiply&lt;/span>(&lt;span style="color:#66d9ef">int&lt;/span> a, &lt;span style="color:#66d9ef">int&lt;/span> b) {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">int&lt;/span> result &lt;span style="color:#f92672">=&lt;/span> a &lt;span style="color:#f92672">*&lt;/span> b;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#66d9ef">return&lt;/span> result;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;#34;EndBrace.h&amp;#34;&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;p>编译成功&lt;/p>
&lt;h2 id="告诉编译器输出一个包含所有结果的文件">告诉编译器输出一个包含所有结果的文件&lt;a class="anchor" href="#%e5%91%8a%e8%af%89%e7%bc%96%e8%af%91%e5%99%a8%e8%be%93%e5%87%ba%e4%b8%80%e4%b8%aa%e5%8c%85%e5%90%ab%e6%89%80%e6%9c%89%e7%bb%93%e6%9e%9c%e7%9a%84%e6%96%87%e4%bb%b6">#&lt;/a>&lt;/h2>
&lt;h1 id="简单例子">简单例子&lt;a class="anchor" href="#%e7%ae%80%e5%8d%95%e4%be%8b%e5%ad%90">#&lt;/a>&lt;/h1>
&lt;p>修改配置&lt;/p>
&lt;p>&lt;mark>这个选项会导致不会生成obj文件&lt;/mark>&lt;/p>
&lt;p>&lt;img src="img/ly-20251213123430917.png" alt="" />&lt;/p>
&lt;blockquote class='book-hint '>
&lt;ol>
&lt;li>编译器只执行第一步：展开 #include 头文件、替换 #define 宏定义、删除注释等。&lt;/li>
&lt;li>预处理完成后，它会把结果直接输出到一个后缀为 .i 的纯文本文件中（例如截图下方的 Math.i）。&lt;/li>
&lt;li>中断后续编译：它不会继续构建语法树（AST），也不会生成 CPU 能执行的机器码。因此，磁盘上不会生成 .obj（或 .exe）文件。&lt;/li>
&lt;/ol>&lt;/blockquote>&lt;p>&lt;img src="img/ly-20251213123454072.png" alt="" />&lt;/p></description></item><item><title>05C++是如何工作的</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/05C++%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84/</link><pubDate>Thu, 11 Dec 2025 19:56:24 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/05C++%E6%98%AF%E5%A6%82%E4%BD%95%E5%B7%A5%E4%BD%9C%E7%9A%84/</guid><description>&lt;p>&lt;em>&lt;strong>C++是如何工作的&lt;/strong>&lt;/em>&lt;/p>
&lt;p>源代码 &amp;ndash;&amp;gt; 程序启动文件&lt;/p>
&lt;p>多个源文件 &lt;em>(编译器)&amp;ndash;&amp;gt;&lt;/em> 二进制(可执行)文件&lt;/p>
&lt;h1 id="分析源码">分析源码&lt;a class="anchor" href="#%e5%88%86%e6%9e%90%e6%ba%90%e7%a0%81">#&lt;/a>&lt;/h1>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c++" data-lang="c++">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*试着编译单个cpp文件 ctrl+f7
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">会生成Main.obj文件*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*/①（编译器处理）include是预处理指令，会在编
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">译前找到iostream这个文件并插入该文件内容*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*②.h文件是在预编译时被处理（插入），并不会被编译；只有
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">.cpp文件会被编译成 .obj文件，链接器把这些合并成 .exe文件*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*③声明，确实有Log函数存在*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">/*④链接器，编译整个项目时，链接器链接时才会去查找这个
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">函数是否真是存在,如果不存在，则会提示&amp;#34;unresolved external
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">symbol&amp;#34;：未解析的外部符号，链接器无法找到定义
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">---链接器的工作是将函数体链接到其标识符(名称)
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">*/&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//参数名message可以省略
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">//void Log(const char* message);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">// &amp;lt;&amp;lt; 重载运算符, 运算符可以理解成函数
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">//类似下面这句：
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	&lt;span style="color:#75715e">// std::cout.print(&amp;#34;hello world!&amp;#34;).print(std:endl);//!!编译无法通过
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hello world!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//Log(&amp;#34;helloworld!&amp;#34;);
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//等待按下回车键来移动到程序的下一行
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	&lt;span style="color:#75715e">//可以不写return，默认返回0，表示正确返回程序
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h1 id="编译">编译&lt;a class="anchor" href="#%e7%bc%96%e8%af%91">#&lt;/a>&lt;/h1>
&lt;p>&lt;img src="img/ly-20251212234000724.png" alt="" />&lt;/p>
&lt;p>项目配置：Debug/Release&lt;/p>
&lt;p>平台配置：x64(windows64位系统),x86(windows32位系统)，android&amp;hellip;.&lt;/p>
&lt;h2 id="项目属性">项目属性&lt;a class="anchor" href="#%e9%a1%b9%e7%9b%ae%e5%b1%9e%e6%80%a7">#&lt;/a>&lt;/h2>
&lt;p>&lt;img src="img/ly-20251212234311524.png" alt="" />&lt;/p>
&lt;p>&lt;img src="img/ly-20251212235352513.png" alt="" />&lt;/p>
&lt;p>Release的时候，Optimization这里都是Maximize（最佳优化）&lt;/p>
&lt;h2 id="按钮添加">按钮添加&lt;a class="anchor" href="#%e6%8c%89%e9%92%ae%e6%b7%bb%e5%8a%a0">#&lt;/a>&lt;/h2>
&lt;p>&lt;img src="img/ly-20251213000727384.png" alt="" />&lt;/p></description></item><item><title>01-04设置cpp</title><link>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/01-04%E8%AE%BE%E7%BD%AEcpp/</link><pubDate>Thu, 15 May 2025 09:43:53 +0800</pubDate><guid>https://blog.liuyi2026.asia/zh/docs/technology/cpp/chernoCPP/01-48/01-04%E8%AE%BE%E7%BD%AEcpp/</guid><description>&lt;h1 id="welcometocpp">WelcomeToCpp&lt;a class="anchor" href="#welcometocpp">#&lt;/a>&lt;/h1>
&lt;ul>
&lt;li>使用c++可以控制CPU应该执行的每条指令&lt;/li>
&lt;li>C++的代码编译后可以在任何平台运行，前提是有一个&lt;mark>为对应平台生成机器代码的编译器&lt;/mark>&lt;/li>
&lt;li>与C++不同，C#或JAVA，他们在虚拟机中运行，运行时将代码从“中间语言”转换为机器代码&lt;/li>
&lt;li>学习新事物的关键就是对事物进行实验&lt;/li>
&lt;li>将讨论如何利用C++库&lt;/li>
&lt;li>C++实际上如何工作&lt;/li>
&lt;li>关于内存和指针：内存区域，智能指针，移动语义，&lt;mark>模板&lt;/mark>&lt;/li>
&lt;li>宏，以及为多个平台编程&lt;/li>
&lt;li>编写自己的数据结构，学习如何使他们比C++标准库中的结构更快&lt;/li>
&lt;li>低级优化，与编译器和汇编相关&lt;/li>
&lt;/ul>
&lt;h1 id="设置c">设置C++&lt;a class="anchor" href="#%e8%ae%be%e7%bd%aec">#&lt;/a>&lt;/h1>
&lt;h2 id="windows平台">windows平台&lt;a class="anchor" href="#windows%e5%b9%b3%e5%8f%b0">#&lt;/a>&lt;/h2>
&lt;ol>
&lt;li>
&lt;p>需要文本编辑器，将C++代码编写为文本文件，传递给编译器以生成某种可执行二进制文件，以便可以运行&lt;/p>
&lt;/li>
&lt;li>
&lt;p>或者跳过1，直接用IDE，即有一套帮助你编写和调试代码的工具。（Visual Studio，视频用的2017，我这里下载的 Visual Studio Community 2022）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>安装勾选：&lt;br>
&lt;img src="img/ly-20251211002453819.png" alt="" />&lt;/p>
&lt;/li>
&lt;li>
&lt;p>新建项目
&lt;img src="img/ly-20251211003119486.png" alt="" />
&lt;img src="img/ly-20251211003146818.png" alt="" />&lt;br>
&lt;img src="img/ly-20251213002433105.png" alt="" /> &lt;br>
&lt;em>不要勾选 Place solution and project in the same directory&lt;/em>&lt;/p>
&lt;p>&lt;mark>解决方案，solution，是一组相互关联的项目&lt;/mark>，他们有各种项目类型，解决方案就像工作台，&lt;mark>每个项目本质上是一组文件，会编译成目标二进制文件&lt;/mark>（无论是库还是实际的可执行文件）&lt;/p>
&lt;/li>
&lt;li>
&lt;p>添加新项
&lt;img src="img/ly-20251211003758014.png" alt="" />&lt;br>
&lt;img src="img/ly-20251211003828009.png" alt="" />&lt;/p>
&lt;/li>
&lt;li>
&lt;p>代码文件(Main.cpp)&lt;/p>
&lt;/li>
&lt;/ol>
&lt;div class="highlight">&lt;pre tabindex="0" style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;">&lt;code class="language-c++" data-lang="c++">&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">#include&lt;/span> &lt;span style="color:#75715e">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span style="color:#75715e">
&lt;/span>&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>&lt;span style="color:#75715e">&lt;/span>&lt;span style="color:#66d9ef">int&lt;/span> &lt;span style="color:#a6e22e">main&lt;/span>() {
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cout &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> &lt;span style="color:#e6db74">&amp;#34;hello world!&amp;#34;&lt;/span> &lt;span style="color:#f92672">&amp;lt;&amp;lt;&lt;/span> std&lt;span style="color:#f92672">::&lt;/span>endl;
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>	std&lt;span style="color:#f92672">::&lt;/span>cin.get();
&lt;/span>&lt;/span>&lt;span style="display:flex;">&lt;span>}&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/div>&lt;h3 id="配置文件修改">配置文件修改&lt;a class="anchor" href="#%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6%e4%bf%ae%e6%94%b9">#&lt;/a>&lt;/h3>
&lt;p>下载ChernoVS.vssettings文件，并放到下面的位置&lt;br>
&lt;em>C:\Users\ly\AppData\Local\Microsoft\VisualStudio\17.0_f89cedea\Settings&lt;/em>&lt;/p>
&lt;p>在vs工具栏中-tools-ImportAndExportSettings-&lt;/p>
&lt;p>ImportSelectedEnvironmentSettings&lt;/p>
&lt;p>选择no,just Import new，选择 ChernoVS.vssetings即可&lt;/p>
&lt;h3 id="运行">运行&lt;a class="anchor" href="#%e8%bf%90%e8%a1%8c">#&lt;/a>&lt;/h3>
&lt;ol>
&lt;li>
&lt;p>右键，构建（项目）&lt;br>
&lt;img src="img/ly-20251211004402649.png" alt="" />&lt;br>
&lt;img src="img/ly-20251211004420988.png" alt="" />&lt;br>
文件系统查看：&lt;/p>
&lt;p>&lt;img src="img/ly-20251211004533630.png" alt="" />&lt;/p>
&lt;/li>
&lt;li>
&lt;p>双击.exe文件，结果：&lt;/p>
&lt;p>&lt;img src="img/ly-20251211004642375.png" alt="" />&lt;br>
按任意键终止&lt;/p>
&lt;/li>
&lt;/ol>
&lt;hr>
&lt;p>或者单机本地的Windows调试器来运行它&lt;/p></description></item></channel></rss>