<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Rust on kenji.blog</title><link>http://kenji.blog/ar/categories/rust/</link><description>Recent content in Rust on kenji.blog</description><generator>Hugo -- gohugo.io</generator><language>ar</language><copyright>kenjinote</copyright><lastBuildDate>Sat, 12 Sep 2026 04:00:00 +0900</lastBuildDate><atom:link href="http://kenji.blog/ar/categories/rust/index.xml" rel="self" type="application/rss+xml"/><item><title>شرح "الملكية" و"الاستعارة" في Rust مقارنة بمؤشرات C++</title><link>http://kenji.blog/ar/p/rust-ownership-borrowing-cpp-pointer-comparison/</link><pubDate>Sat, 12 Sep 2026 04:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/rust-ownership-borrowing-cpp-pointer-comparison/</guid><description>&lt;img src="http://kenji.blog/p/rust-ownership-borrowing-cpp-pointer-comparison/img/eyecatch.jpg" alt="Featured image of post شرح "الملكية" و"الاستعارة" في Rust مقارنة بمؤشرات C++" />&lt;p>في برمجة الأنظمة الحديثة، يمثل تحقيق التوازن بين الأداء وأمان الذاكرة تحديًا مستمرًا. لفترة طويلة، سيطرت C++ على هذا المجال كملك متوج، ولكن في السنوات الأخيرة، بدأت لغة Rust في تهديد هذه المكانة. تتمثل الميزة الأبرز في Rust في مفهومي &amp;ldquo;الملكية (Ownership)&amp;rdquo; و&amp;quot;الاستعارة (Borrowing)&amp;quot;، اللذين يضمنان أمان الذاكرة في وقت الترجمة دون الحاجة إلى جامع قمامة (Garbage Collection).&lt;/p>
&lt;p>في هذه المقالة، سنقارن بالتفصيل بين مؤشرات C++ (المؤشرات الخام، &lt;code>std::unique_ptr&lt;/code>، &lt;code>std::shared_ptr&lt;/code>) ونموذج الملكية في Rust. سنشرح بشكل شامل كيف يمنع مترجم Rust (مدقق الاستعارة أو Borrow Checker) أخطاء مثل الاستخدام بعد التحرير (Use-After-Free) وسباق البيانات (Data Race)، وذلك مدعومًا بأمثلة برمجية ورسوم توضيحية.&lt;/p>
&lt;h2 id="1-أساسيات-إدارة-الذاكرة-المكدس-stack-والكومة-heap">1. أساسيات إدارة الذاكرة: المكدس (Stack) والكومة (Heap)
&lt;/h2>&lt;p>لفهم أساسيات إدارة الذاكرة، دعونا نراجع أولاً كيف يستخدم البرنامج الذاكرة. تنقسم مساحة الذاكرة بشكل رئيسي إلى &amp;ldquo;المكدس (Stack)&amp;rdquo; و&amp;quot;الكومة (Heap)&amp;quot;.&lt;/p>
&lt;h3 id="المكدس-stack">المكدس (Stack)
&lt;/h3>&lt;p>هي المنطقة التي يتم فيها تكديس المتغيرات المحلية وغيرها عند استدعاء الدوال. تتميز بهيكل LIFO (ما يدخل أخيرًا يخرج أولاً)، وتكون عملية تخصيص الذاكرة وتحريرها سريعة جدًا. يتم وضع البيانات التي يمكن تحديد حجمها في وقت الترجمة (Compile time) فقط هنا.&lt;/p>
&lt;h3 id="الكومة-heap">الكومة (Heap)
&lt;/h3>&lt;p>يتم فيها وضع البيانات التي يُحدد حجمها ديناميكيًا في وقت التشغيل (Runtime)، أو البيانات التي تحتاج إلى البقاء بعد انتهاء نطاق الدالة (Scope). يتم الوصول إليها عبر المؤشرات (Pointers) أو المراجع (References).&lt;/p>
&lt;p>في اللغات التي لا تحتوي على جامع قمامة مثل C++ وRust، يمكن صياغة تكلفة إدارة ذاكرة الكومة بمعادلة رياضية كالتالي. بافتراض أن إجمالي عدد الكائنات هو $N$، ومتوسط الوقت المستغرق في التخصيص هو $T_{alloc}$، ومتوسط الوقت المستغرق في التحرير هو $T_{dealloc}$، فإن إجمالي تكلفة إدارة الذاكرة $C_{memory}$ يكون:&lt;/p>
$$ C_{memory} = \sum_{i=1}^{N} (T_{alloc, i} + T_{dealloc, i}) + O_{sync} $$
&lt;p>حيث يمثل $O_{sync}$ النفقات الإضافية (Overhead) للتحكم الحصري (مثل كائنات المزامنة Mutex والعمليات الذرية Atomic operations) في بيئة متعددة الخيوط (Multithreaded). نظرًا لأن Rust تحدد توقيت تحرير الذاكرة في وقت الترجمة، فإنها تقضي على مشكلة انخفاض الإنتاجية (Stop-The-World) الناتجة عن جامع القمامة في وقت التشغيل، وتنفذ $T_{dealloc}$ في وقت آمن ومؤكد.&lt;/p>
&lt;div class="mermaid">graph TD
A["ذاكرة البرنامج"] --> B["المكدس (سريع، حجم ثابت)"]
A --> C["الكومة (ديناميكي، أبطأ)"]
B --> D["المتغيرات المحلية"]
B --> E["المؤشرات/المراجع"]
C --> F["بيانات مخصصة ديناميكيًا"]
E -.->|"يشير إلى"| F&lt;/div>
&lt;h2 id="2-مؤشرات-c-مقايضة-بين-الحرية-والخطر">2. مؤشرات C++: مقايضة بين الحرية والخطر
&lt;/h2>&lt;p>دعونا نلقي نظرة على تطور إدارة الذاكرة في C++.&lt;/p>
&lt;h3 id="عصر-المؤشرات-الخام-raw-pointers-ومشاكلها">عصر المؤشرات الخام (Raw Pointers) ومشاكلها
&lt;/h3>&lt;p>توفر المؤشرات الخام (&lt;code>*&lt;/code>)، الموروثة من لغة C، حرية مطلقة، ولكنها في الوقت نفسه تعتبر بيئة خصبة لأخطاء خطيرة مثل:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>تسرب الذاكرة (Memory Leak)&lt;/strong>: نسيان استخدام &lt;code>delete&lt;/code> للذاكرة المخصصة بواسطة &lt;code>new&lt;/code>.&lt;/li>
&lt;li>&lt;strong>المؤشرات المتدلية (Dangling Pointer)&lt;/strong>: الوصول إلى مؤشر يشير إلى ذاكرة تم تحريرها (بعد &lt;code>delete&lt;/code>).&lt;/li>
&lt;li>&lt;strong>التحرير المزدوج (Double Free)&lt;/strong>: استخدام &lt;code>delete&lt;/code> لنفس مساحة الذاكرة مرتين.&lt;/li>
&lt;/ul>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++: مثال على المشاكل الناجمة عن المؤشرات الخام
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="kt">void&lt;/span> &lt;span class="nf">rawPointerExample&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="kt">int&lt;/span>&lt;span class="o">*&lt;/span> &lt;span class="n">ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// ... بعض العمليات ...
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">delete&lt;/span> &lt;span class="n">ptr&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// الوصول عن طريق الخطأ مرة أخرى (Use-After-Free / Dangling Pointer)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// لا يستطيع مترجم C++ تحويل هذا إلى خطأ في وقت الترجمة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ptr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span> &lt;span class="c1">// سلوك غير محدد (Undefined Behavior)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="ظهور-raii-والمؤشرات-الذكية-بداية-من-c11">ظهور RAII والمؤشرات الذكية (بداية من C++11)
&lt;/h3>&lt;p>منذ C++11، تم توحيد المؤشرات الذكية المبنية على مفهوم RAII (اكتساب الموارد هو التهيئة)، وأصبح الاستخدام المباشر للمؤشرات الخام غير محبذ.&lt;/p>
&lt;h4 id="stdunique_ptr">&lt;code>std::unique_ptr&lt;/code>
&lt;/h4>&lt;p>مؤشر يمثل ملكية حصرية (فردية). يتم تحرير الذاكرة تلقائيًا بمجرد الخروج من النطاق. لا يمكن نسخه، بل يُسمح فقط بـ &amp;ldquo;نقل (Move)&amp;rdquo; الملكية (باستخدام &lt;code>std::move&lt;/code>).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++: std::unique_ptr
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">uniquePtrExample&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">p1&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_unique&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">42&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// std::unique_ptr&amp;lt;int&amp;gt; p2 = p1; // خطأ في وقت الترجمة (النسخ غير مسموح)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">p3&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">p1&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// نقل الملكية
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// نقطة ضعف C++: بعد النقل، يصبح p1 مساويًا لـ nullptr، ولكن الوصول إليه لا يزال قابلاً للترجمة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// سيؤدي ذلك إلى انهيار (Segmentation fault) في وقت التشغيل
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// std::cout &amp;lt;&amp;lt; *p1 &amp;lt;&amp;lt; std::endl;
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h4 id="stdshared_ptr">&lt;code>std::shared_ptr&lt;/code>
&lt;/h4>&lt;p>مؤشر يسمح لمؤشرات متعددة بمشاركة نفس الكائن. يستخدم عداد المراجع (Reference Counting)، وبمجرد وصول العداد إلى 0، يتم تحرير الذاكرة. يتطلب عمليات زيادة ونقصان ذرية (Atomic)، مما يسبب نفقات إضافية طفيفة في الأداء (تعادل $O_{sync}$ المذكور سابقًا).&lt;/p>
&lt;h2 id="3-الملكية-ownership-في-rust-نقلة-نوعية">3. الملكية (Ownership) في Rust: نقلة نوعية
&lt;/h2>&lt;p>تضع Rust مفهوم &lt;code>std::unique_ptr&lt;/code> الخاص بـ C++ كجوهر لمواصفات اللغة، مع تطبيق &amp;ldquo;نموذج ملكية&amp;rdquo; أكثر صرامة.&lt;/p>
&lt;h3 id="القواعد-الثلاث-للملكية">القواعد الثلاث للملكية
&lt;/h3>&lt;p>يعتمد نظام الملكية في Rust على ثلاث قواعد بسيطة للغاية:&lt;/p>
&lt;ol>
&lt;li>&lt;strong>كل قيمة في Rust تمتلك متغيرًا يُسمى &amp;ldquo;المالك&amp;rdquo; (Owner).&lt;/strong>&lt;/li>
&lt;li>&lt;strong>يمكن أن يكون هناك مالك واحد فقط في أي وقت.&lt;/strong>&lt;/li>
&lt;li>&lt;strong>عندما يخرج المالك من النطاق (Scope)، سيتم تدمير القيمة.&lt;/strong>&lt;/li>
&lt;/ol>
&lt;p>في Rust، يتم &amp;ldquo;نقل&amp;rdquo; الموارد افتراضيًا. تنتقل الملكية عن طريق عملية التعيين دون الحاجة إلى تحديد &lt;code>std::move&lt;/code> صراحة كما في C++.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt">1
&lt;/span>&lt;span class="lnt">2
&lt;/span>&lt;span class="lnt">3
&lt;/span>&lt;span class="lnt">4
&lt;/span>&lt;span class="lnt">5
&lt;/span>&lt;span class="lnt">6
&lt;/span>&lt;span class="lnt">7
&lt;/span>&lt;span class="lnt">8
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Rust: نقل الملكية (Move)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">String&lt;/span>::&lt;span class="n">from&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;hello&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// بيانات مخصصة في الكومة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// تنتقل الملكية من s1 إلى s2 (موف)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// الفرق الأكبر مع C++: الوصول إلى متغير بعد نقله يؤدي إلى &amp;#34;خطأ في وقت الترجمة&amp;#34;!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// println!(&amp;#34;{}, world!&amp;#34;, s1); // خطأ في الترجمة: value borrowed here after move
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>ميزة &amp;ldquo;جعل الوصول إلى المتغيرات بعد النقل مستحيلاً في وقت الترجمة&amp;rdquo; هي أحد الأسباب التي تجعل Rust أكثر أمانًا من &lt;code>std::unique_ptr&lt;/code> في C++.&lt;/p>
&lt;div class="mermaid">sequenceDiagram
participant S1 as "المتغير s1"
participant Heap as "ذاكرة الكومة ('hello')"
participant S2 as "المتغير s2"
S1->>Heap: "يخصص ويملك"
Note over S1,S2: "let s2 = s1;"
S1--xHeap: "يفقد الملكية (مُبطل)"
S2->>Heap: "يأخذ الملكية"&lt;/div>
&lt;h2 id="4-الاستعارة-borrowing-والمراجع">4. الاستعارة (Borrowing) والمراجع
&lt;/h2>&lt;p>إذا كانت الملكية تنتقل باستمرار، فسيتعين إرجاع الملكية في كل مرة يتم فيها تمرير قيمة إلى دالة، وهو أمر غير مريح للغاية. وهنا يأتي دور &amp;ldquo;الاستعارة (Borrowing)&amp;rdquo;. وهو يعادل المؤشرات أو المراجع في C++.&lt;/p>
&lt;p>هناك نوعان من الاستعارة في Rust:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>المرجع غير القابل للتغيير (Immutable Reference)&lt;/strong>: &lt;code>&amp;amp;T&lt;/code> (مشابه لـ &lt;code>const T&amp;amp;&lt;/code> في C++)&lt;/li>
&lt;li>&lt;strong>المرجع القابل للتغيير (Mutable Reference)&lt;/strong>: &lt;code>&amp;amp;mut T&lt;/code> (مشابه لـ &lt;code>T&amp;amp;&lt;/code> في C++)&lt;/li>
&lt;/ul>
&lt;h3 id="القانون-الصارم-لمدقق-الاستعارة-borrow-checker">القانون الصارم لمدقق الاستعارة (Borrow Checker)
&lt;/h3>&lt;p>يحتوي مترجم Rust على &amp;ldquo;مدقق الاستعارة&amp;rdquo; الذي يتحقق من صحة المراجع. يفرض مدقق الاستعارة القواعد الصارمة التالية:&lt;/p>
&lt;blockquote>
&lt;p>في أي نطاق معين، يمكن أن يوجد واحد فقط مما يلي:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>مرجع واحد قابل للتغيير (&lt;code>&amp;amp;mut T&lt;/code>)&lt;/strong>&lt;/li>
&lt;li>&lt;strong>عدة مراجع غير قابلة للتغيير (&lt;code>&amp;amp;T&lt;/code>)&lt;/strong>&lt;/li>
&lt;/ul>
&lt;/blockquote>
&lt;p>يُعرف هذا بمبدأ &lt;strong>&amp;ldquo;قراء متعددون أو كاتب واحد (MRSW)&amp;rdquo; (Multiple Readers XOR Single Writer)&lt;/strong>. يمكن التعبير عن ذلك بواسطة المعامل الرياضي (XOR) (الاستبعاد المنطقي). بالنسبة للحالة $S$، يجب أن يفي عدد المراجع غير القابلة للتغيير $N_r$ وعدد المراجع القابلة للتغيير $N_w$ بالشرط التالي:&lt;/p>
$$ (N_r \ge 0 \land N_w = 0) \oplus (N_r = 0 \land N_w = 1) $$
&lt;p>من خلال هذه القاعدة، يتم &lt;strong>منع سباق البيانات (Data Race) تمامًا في وقت الترجمة&lt;/strong>. يحدث سباق البيانات عندما: (1) يصل مؤشران أو أكثر إلى نفس البيانات في وقت واحد، (2) يقوم واحد على الأقل بالكتابة، و (3) لا توجد آلية للمزامنة. تمنع Rust سباق البيانات مسبقًا عن طريق تدمير الشرط (2) في وقت الترجمة.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Rust: خطأ في وقت الترجمة بسبب انتهاك قواعد الاستعارة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">String&lt;/span>::&lt;span class="n">from&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;hello&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r1&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// استعارة غير قابلة للتغيير (موافق)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// استعارة غير قابلة للتغيير (موافق)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// let r3 = &amp;amp;mut s; // خطأ! لا يمكن إنشاء استعارة قابلة للتغيير بينما توجد استعارة غير قابلة للتغيير
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">, &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">r2&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="5-منع-إبطال-المكرر-iterator-invalidation">5. منع إبطال المكرر (Iterator Invalidation)
&lt;/h2>&lt;p>كمثال عملي يبرز قوة مدقق الاستعارة بشكل أفضل، دعونا نلقي نظرة على الخلل الكلاسيكي المعروف باسم &amp;ldquo;إبطال المكرر&amp;rdquo;.&lt;/p>
&lt;h3 id="إبطال-المكرر-في-c-انهيار-وقت-التشغيل">إبطال المكرر في C++ (انهيار وقت التشغيل)
&lt;/h3>&lt;p>عند تعديل &lt;code>std::vector&lt;/code> في C++ داخل حلقة تكرارية، هناك احتمال أن يتم إعادة تخصيص الذاكرة الأساسية (Reallocation)، مما يحول المرجع إلى مؤشر متدلٍ (Dangling Pointer).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// C++: خطأ إبطال المكرر
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">v&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="p">{&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span> &lt;span class="mi">3&lt;/span>&lt;span class="p">};&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// الحصول على مرجع لعنصر في المتجه
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;amp;&lt;/span> &lt;span class="n">first&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// إضافة عنصر (إذا كانت السعة غير كافية هنا، فسيتم تخصيص مساحة ذاكرة جديدة،
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// وقد يتم التخلص من المساحة القديمة)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">v&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">4&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// قد يشير first بالفعل إلى ذاكرة تم تحريرها! (سلوك غير محدد)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;The first element is: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">first&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h3 id="حماية-وقت-الترجمة-بواسطة-rust">حماية وقت الترجمة بواسطة Rust
&lt;/h3>&lt;p>دعونا نكتب نفس المنطق تمامًا باستخدام Rust.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="c1">// Rust: منع إبطال المكرر في وقت الترجمة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">v&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">vec!&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">3&lt;/span>&lt;span class="p">];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// الحصول على مرجع غير قابل للتغيير (بدء الاستعارة)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">first&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">v&lt;/span>&lt;span class="p">[&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// خطأ! طالما أن `first` يستعير `v` بشكل غير قابل للتغيير،
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// لا يمكنك إجراء استعارة قابلة للتغيير المطلوبة لـ `v.push`.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// v.push(4);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;The first element is: &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">first&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>وبهذه الطريقة، تمنع Rust على مستوى المترجم &amp;ldquo;تعديل القيمة (استعارة قابلة للتغيير) أثناء قراءتها (استعارة غير قابلة للتغيير)&amp;quot;، مما يضمن اكتشاف الأخطاء القاتلة مثل الاستخدام بعد التحرير (Use-After-Free) وإبطال المكرر في وقت الترجمة بشكل مؤكد.&lt;/p>
&lt;div class="mermaid">graph LR
A["المتغير v (المالك)"] --> B["مصفوفة الكومة [1, 2, 3]"]
C["المرجع 'first' (&amp;v[0])"] -.->|"استعارة غير قابلة للتغيير"| B
A -->|X "استعارة قابلة للتغيير مرفوضة!"| D["v.push(4)"]
style C stroke:#00FF00,stroke-width:2px
style D stroke:#FF0000,stroke-width:2px&lt;/div>
&lt;h2 id="6-الملكية-المشتركة-في-rust-rc-و-arc">6. الملكية المشتركة في Rust: &lt;code>Rc&lt;/code> و &lt;code>Arc&lt;/code>
&lt;/h2>&lt;p>توفر Rust أيضًا ملكية مشتركة تعادل &lt;code>std::shared_ptr&lt;/code> في C++، ولكن هناك تمييز واضح في الأنواع للاستخدام في خيط واحد (Single Thread) أو عبر خيوط متعددة (Multi-thread).&lt;/p>
&lt;h3 id="للخيط-الواحد-rct-reference-counted">للخيط الواحد: &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> (Reference Counted)
&lt;/h3>&lt;p>&lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> هو مؤشر ذكي يعتمد على عد المراجع ولكنه ليس آمنًا للخيوط (Non-thread-safe). نظرًا لأنه يزيد أو ينقص العداد دون استخدام تعليمات ذرية، فهو سريع جدًا داخل خيط واحد. ومع ذلك، إذا حاولت إرساله إلى خيط آخر، فسيحدث خطأ في الترجمة (لأنه لا ينفذ سمة &lt;code>Send&lt;/code>).&lt;/p>
&lt;h3 id="للخيوط-المتعددة-arct-atomic-reference-counted">للخيوط المتعددة: &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> (Atomic Reference Counted)
&lt;/h3>&lt;p>للمشاركة بين الخيوط، يتم استخدام &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> الذي يقوم بعمليات زيادة ونقصان ذرية (Atomic). تتكبد تكلفة تعادل &lt;code>std::shared_ptr&lt;/code> في C++.&lt;/p>
&lt;p>علاوة على ذلك، في C++، إذا حاولت عدة خيوط الكتابة في نفس الوقت إلى متغير مشترك بواسطة &lt;code>std::shared_ptr&lt;/code>، فسيحدث سباق بيانات. لمنع ذلك، يجب استخدام &lt;code>std::mutex&lt;/code> بشكل صحيح يدويًا.&lt;/p>
&lt;p>من ناحية أخرى في Rust، لا يمكن لـ &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> &lt;strong>تغيير البيانات الداخلية بمفرده&lt;/strong>. إذا كانت التعديلات ضرورية، يجب دمجه مع كائن مزامنة &lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">sync&lt;/span>::&lt;span class="p">{&lt;/span>&lt;span class="n">Arc&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Mutex&lt;/span>&lt;span class="p">};&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">thread&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// مزيج من المشاركة الآمنة للخيوط والتحكم الحصري
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// مشابه لـ std::shared_ptr&amp;lt;std::mutex&amp;gt; في C++، لكن المتيوتكس (Mutex) هنا يغلف البيانات
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">counter&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Arc&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Mutex&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="p">));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">vec!&lt;/span>&lt;span class="p">[];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">_&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">..&lt;/span>&lt;span class="mi">10&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">counter_clone&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Arc&lt;/span>::&lt;span class="n">clone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">counter&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">thread&lt;/span>::&lt;span class="n">spawn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">move&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">||&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// عن طريق استدعاء lock()، يمكنك الحصول على مرجع قابل للتغيير (&amp;amp;mut i32) داخليًا
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">counter_clone&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">num&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">+=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">});&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// يتم تحرير القفل تلقائيا عند الخروج من النطاق بسبب مبدأ RAII
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Result: &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">*&lt;/span>&lt;span class="n">counter&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">());&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>والجدير بالذكر أن &lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code> في Rust ليس مجرد آلية قفل فحسب، بل &lt;strong>&amp;ldquo;يغلف البيانات التي يجب حمايتها كنوع&amp;rdquo;&lt;/strong>. يمنع هذا التصميم بالكامل خطأ &amp;ldquo;الوصول إلى البيانات ونسيان القفل&amp;rdquo; على مستوى الترجمة. النظام مبني بحيث لا يمكنك الحصول على حق الوصول (مرجع) للبيانات الداخلية دون الحصول على القفل أولاً (&lt;code>lock()&lt;/code>).&lt;/p>
&lt;h2 id="الخلاصة-فحص-مسبق-بواسطة-المترجم-أم-مسؤولية-شخصية-للمطور">الخلاصة: &amp;ldquo;فحص مسبق&amp;rdquo; بواسطة المترجم أم &amp;ldquo;مسؤولية شخصية&amp;rdquo; للمطور؟
&lt;/h2>&lt;p>توفر المؤشرات والمؤشرات الذكية في C++ للمطور تحكمًا متقدمًا وأداءً عاليًا، ولكن الاستخدام الصحيح لها يعتمد على انضباط المطور. على الرغم من أن C++ أصبحت أكثر أمانًا بشكل دراماتيكي مع إدخال RAII و &lt;code>std::unique_ptr&lt;/code>، إلا أنها لا تستطيع منع &amp;ldquo;السلوك غير المحدد&amp;rdquo; تمامًا على مستوى اللغة، مثل الوصول بعد النقل أو إبطال المكرر.&lt;/p>
&lt;p>من ناحية أخرى، من خلال تضمين قواعد الملكية (Ownership) والاستعارة (Borrowing) في المترجم، تكتشف Rust هذه الأخطاء &lt;strong>في وقت الترجمة&lt;/strong> بدلاً من وقت التشغيل. إن الضمان القوي المتمثل في &amp;ldquo;إذا نجحت عملية الترجمة، فإن الذاكرة آمنة&amp;rdquo; هو السبب الأكبر الذي جعل Rust تكتسب دعمًا سريعًا في برمجة الأنظمة.&lt;/p>
&lt;p>على الرغم من أن القتال ضد مدقق الاستعارة في Rust (Fight the borrow checker) يمثل عقبة كبيرة للمبتدئين، إلا أنه في الواقع قيام المترجم بالنيابة عنك بعملية حسابية معقدة تتمثل في &amp;ldquo;تتبع مدة بقاء المؤشر&amp;rdquo;، والتي كان مبرمجو C++ يقومون بها عادة في رؤوسهم.&lt;/p>
&lt;p>إذا تعلمت Rust بعد فهم حرية ومخاطر مؤشرات C++، فيجب أن تكون قادرًا على فهم أعمق للفلسفة الكامنة وراء نموذج الملكية و&amp;quot;لماذا تم اعتماده بهذا التصميم&amp;rdquo;.&lt;/p>
&lt;hr>
&lt;p>&lt;em>هذه المقالة هي دراسة مقارنة حول طرق إدارة الذاكرة في C++ و Rust. نأمل أن تكون بمثابة مرجع لاختيار اللغة المناسبة وفقًا لمتطلبات كل مشروع.&lt;/em>&lt;/p></description></item><item><title>مهندس C++ يشارك تجربته في تعلم Rust: المزايا والعيوب</title><link>http://kenji.blog/ar/p/cpp-engineer-learning-rust-pros-cons/</link><pubDate>Sat, 12 Sep 2026 03:00:00 +0900</pubDate><guid>http://kenji.blog/ar/p/cpp-engineer-learning-rust-pros-cons/</guid><description>&lt;img src="http://kenji.blog/p/cpp-engineer-learning-rust-pros-cons/img/eyecatch.jpg" alt="Featured image of post مهندس C++ يشارك تجربته في تعلم Rust: المزايا والعيوب" />&lt;h1 id="مقدمة-فجر-جديد-في-برمجة-النظم">مقدمة: فجر جديد في برمجة النظم
&lt;/h1>&lt;p>في هندسة البرمجيات الحديثة، يقف كل من C++ و Rust كعملاقين في طليعة برمجة النظم. لسنوات عديدة، تربعت C++ كملك مطلق في مجالات مثل أنظمة التشغيل، والأجهزة المدمجة، ومحركات الألعاب، وأنظمة التداول عالي التردد (HFT)، حيث يتطلب الأمر استخراج أقصى درجات الأداء من العتاد. بصفتي مهندس C++ أول، بدأت مسيرتي من غابة المؤشرات الخام في حقبة C++98، وواصلت كتابة التعليمات البرمجية بالتزامن مع موجة التحديث التي جلبتها C++11 (إدخال المؤشرات الذكية، وتعبيرات لامدا، و &lt;code>auto&lt;/code>)، وصولاً إلى التوسع الهائل في المواصفات مع إصدارات C++14/17/20.&lt;/p>
&lt;p>ولكن في السنوات الأخيرة، شهدنا صعودًا دراماتيكيًا للغة Rust كحل للمشاكل الهيكلية التي تعاني منها C++ — وتحديدًا &amp;ldquo;الافتقار إلى أمان الذاكرة&amp;rdquo; والذي يؤدي إلى ثغرات أمنية (يُقال إن حوالي 70% من ثغرات CVE ناتجة عن أخطاء في الذاكرة) و &amp;ldquo;المواصفات المعقدة بلا حدود والسلوك غير المحدد (UB)&amp;rdquo;. إن اعتمادها الرسمي في نواة Linux، ومشاريع الانتقال واسعة النطاق إلى Rust من قبل شركات التكنولوجيا العملاقة مثل Microsoft و Google و AWS، لا يعتبر مجرد صيحة عابرة، بل يمثل تحولًا جذريًا في نموذج برمجة النظم.&lt;/p>
&lt;p>في هذا المقال، سأقوم بصفتي مهندس C++ متمرس غاص بعمق في تعلم Rust واستخدمها في مشاريع فعلية، بمقارنة وشرح &amp;ldquo;المزايا&amp;rdquo; و &amp;ldquo;العيوب&amp;rdquo; من منظور تقني أساسي يتعلق بمواصفات اللغة.&lt;/p>
&lt;hr>
&lt;h1 id="1-التحول-النموذجي-في-إدارة-الذاكرة-من-raii-إلى-الملكية-والاستعارة">1. التحول النموذجي في إدارة الذاكرة: من RAII إلى الملكية والاستعارة
&lt;/h1>&lt;h2 id="حدود-raii-في-c-والمؤشرات-الذكية">حدود RAII في C++ والمؤشرات الذكية
&lt;/h2>&lt;p>أحد أعظم ابتكارات C++ هو &lt;strong>RAII (اكتساب المورد هو تهيئة)&lt;/strong>. هذا المفهوم، الذي يتم فيه تخصيص الموارد في المنشئ (Constructor) وتحريرها تلقائيًا في المدمر (Destructor) عند الخروج من النطاق، قد حرر المطورين من الرعب الناتج عن تسرب الذاكرة بسبب استخدام &lt;code>new&lt;/code> و &lt;code>delete&lt;/code> يدويًا. بدءًا من C++11، تمت إضافة &lt;code>std::unique_ptr&lt;/code> و &lt;code>std::shared_ptr&lt;/code> إلى المكتبة القياسية، مما جعل مفهوم الملكية (Ownership) قابلًا للتعبير عنه في الشيفرة.&lt;/p>
&lt;p>مع ذلك، فإن المؤشرات الذكية ودلالات النقل (Move Semantics) في C++ تعاني من نقطة ضعف قاتلة تتمثل في عدم اكتمال التحقق الثابت (Static Verification) من قبل المترجم (Compiler).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;span class="lnt">24
&lt;/span>&lt;span class="lnt">25
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;memory&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;string&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">unique_ptr&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">ptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Consuming: &amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="o">*&lt;/span>&lt;span class="n">ptr&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">auto&lt;/span> &lt;span class="n">my_ptr&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">make_unique&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">string&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Hello, C++&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// نقل (Move) الملكية إلى الدالة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">move&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">my_ptr&lt;/span>&lt;span class="p">));&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// خطر: في C++، الوصول إلى كائن بعد نقله لا يؤدي إلى خطأ في الترجمة
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// std::move هو مجرد تحويل إلى مرجع قيمة يمينية (T&amp;amp;&amp;amp;)، والمترجم لا يمنع استخدامه
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">if&lt;/span> &lt;span class="p">(&lt;/span>&lt;span class="n">my_ptr&lt;/span>&lt;span class="p">)&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Pointer is still valid?&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span> &lt;span class="k">else&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">cout&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="s">&amp;#34;Pointer is null.&amp;#34;&lt;/span> &lt;span class="o">&amp;lt;&amp;lt;&lt;/span> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">endl&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// std::cout &amp;lt;&amp;lt; *my_ptr &amp;lt;&amp;lt; std::endl; // سلوك غير محدد بسبب استخدام الذاكرة بعد تحريرها (Use-After-Free)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في C++، هناك دائمًا خطر الوصول الخاطئ إلى كائن تم إفراغه (في حالة صالحة ولكن غير محددة) باستخدام &lt;code>std::move&lt;/code>. يؤدي هذا إلى انهيار البرنامج أثناء التشغيل، أو في أسوأ الحالات، إلى ثغرة أمنية مباشرة.&lt;/p>
&lt;h2 id="الملكية-ownership-في-rust-والدفاع-المطلق-لمدقق-الاستعارة">الملكية (Ownership) في Rust والدفاع المطلق لمدقق الاستعارة
&lt;/h2>&lt;p>تدمج Rust مفهوم &amp;ldquo;الملكية&amp;rdquo; في التصميم الأساسي للغة، وتُجري تحليلًا ثابتًا صارمًا من خلال ميزة في المترجم تُعرف باسم &lt;strong>مدقق الاستعارة (Borrow Checker)&lt;/strong>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">fn&lt;/span> &lt;span class="nf">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">s&lt;/span>: &lt;span class="nb">String&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Consuming: &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">s&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// هنا يخرج s من النطاق، ويتم تحرير الذاكرة (Drop)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">my_string&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">String&lt;/span>::&lt;span class="n">from&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Hello, Rust&amp;#34;&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// نقل الملكية إلى الدالة. في Rust، السلوك الافتراضي هو دلالات النقل.
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">consume&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">my_string&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// خطأ في الترجمة! لا يمكن مطلقًا الوصول إلى المتغير بعد نقله
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="c1">// println!(&amp;#34;Is it still there? {}&amp;#34;, my_string);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>في Rust، بمجرد انتقال ملكية المتغير، يعامله المترجم على أنه في حالة تعادل &amp;ldquo;غير مهيأ&amp;rdquo;، ويمنع تمامًا أي وصول لاحق إليه. نتيجة لذلك، فإن الأخطاء مثل &amp;ldquo;استخدام الذاكرة بعد تحريرها (Use-After-Free)&amp;rdquo; أو &amp;ldquo;المؤشر المتدلي (Dangling Pointer)&amp;rdquo; نظريًا لا يمكنها اجتياز عملية الترجمة.&lt;/p>
&lt;div class="mermaid">graph TD
A["C++ std::unique_ptr"] --> B["تطبيق std::move"]
B --> C["انتقال الملكية"]
C --> D["لا يزال بالإمكان الوصول للمؤشر القديم"]
D --> E["احتمال حدوث سلوك غير محدد (UB)"]
F["Rust Box / String"] --> G["التمرير كقيمة (نقل)"]
G --> H["انتقال الملكية"]
H --> I["المترجم يمنع استخدام المتغير القديم"]
I --> J["ضمان أمان الذاكرة"]&lt;/div>
&lt;h2 id="الاستعارة-borrowing-والتحكم-في-القابلية-للتغيير">الاستعارة (Borrowing) والتحكم في القابلية للتغيير
&lt;/h2>&lt;p>الأقوى من ذلك هو قواعد &amp;ldquo;الاستعارة (Borrowing)&amp;rdquo; التي تشير إلى الموارد. تفرض Rust القواعد التالية:&lt;/p>
&lt;ol>
&lt;li>في أي وقت، يمكن أن يوجد &lt;strong>إما&lt;/strong> &amp;ldquo;عدة مراجع غير قابلة للتغيير (&lt;code>&amp;amp;T&lt;/code>)&amp;rdquo; &lt;strong>أو&lt;/strong> &amp;ldquo;مرجع واحد قابل للتغيير (&lt;code>&amp;amp;mut T&lt;/code>)&amp;rdquo;.&lt;/li>
&lt;li>يجب ألا يعيش المرجع فترة أطول من النطاق الخاص بالبيانات الأصلية (قيود دورة الحياة - Lifetime).&lt;/li>
&lt;/ol>
&lt;p>في C++، من السهل إنشاء مراجع أو مؤشرات متعددة قابلة للتغيير (Mutable) لنفس الكائن، مما قد يؤدي إلى تدمير غير متوقع للحالة (مثل إبطال المكرر - Iterator Invalidation). تمنع Rust هذا المزيج من &amp;ldquo;الأسماء المستعارة (Aliasing) + القابلية للتغيير (Mutability)&amp;rdquo; على مستوى اللغة، مما يمنع الأخطاء قبل حدوثها.&lt;/p>
&lt;hr>
&lt;h1 id="2-تخطيط-الذاكرة-والنفقات-الرياضية-للمؤشرات-الذكية">2. تخطيط الذاكرة والنفقات الرياضية للمؤشرات الذكية
&lt;/h1>&lt;p>في برمجة النظم، الفهم الدقيق لتخطيط الذاكرة أمر لا غنى عنه. دعونا نقارن بين &lt;code>std::shared_ptr&lt;/code> في C++ و &lt;code>std::rc::Rc&lt;/code> / &lt;code>std::sync::Arc&lt;/code> في Rust.&lt;/p>
&lt;p>يدير &lt;code>std::shared_ptr&lt;/code> في C++ الموارد عن طريق حساب المراجع، لكنه يستخدم افتراضيًا عمليات ذرية آمنة خيطيًا (&lt;code>std::atomic&lt;/code>) لزيادة أو تقليل عدد المراجع. يمكن صياغة النفقات العامة على الذاكرة على النحو التالي:&lt;/p>
$$ Overhead_{C++} = sizeof(T) + sizeof(ControlBlock) $$
&lt;p>هنا، تتضمن $ControlBlock$ &amp;ldquo;عداد المراجع القوية (Strong Ref Count)&amp;quot;، و &amp;ldquo;عداد المراجع الضعيفة (Weak Ref Count)&amp;quot;، و &amp;ldquo;المحذف المخصص (Custom Deleter)&amp;rdquo;. تكمن المشكلة في أنه حتى في الحالات التي يتم فيها استخدامه في خيط واحد (Single-thread)، فإن النفقات العامة للتعليمات الذرية (مثل قفل خط ذاكرة التخزين المؤقت) تحدث دون قيد أو شرط.&lt;/p>
&lt;p>في المقابل، تفصل Rust بصرامة المؤشرات الذكية حسب الغرض:&lt;/p>
&lt;ul>
&lt;li>&lt;strong>لخيط واحد&lt;/strong>: &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> (Reference Counted)&lt;/li>
&lt;li>&lt;strong>لخيوط متعددة&lt;/strong>: &lt;code>Arc&amp;lt;T&amp;gt;&lt;/code> (Atomic Reference Counted)&lt;/li>
&lt;/ul>
$$ Overhead_{Rc} = sizeof(T) + 2 \times sizeof(usize) $$
$$ Overhead_{Arc} = sizeof(T) + 2 \times sizeof(AtomicUsize) $$
&lt;p>في Rust، إذا استخدمت &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> المخصص للخيط الواحد، يمكنك تجنب عقوبة العمليات الذرية بالكامل (تجريد بتكلفة صفرية - Zero-cost abstraction). ومن خلال آلية أمان الخيوط التي سيتم مناقشتها لاحقًا، يتم منع تمرير &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> عن طريق الخطأ إلى خيط آخر تمامًا بواسطة نظام الأنواع.&lt;/p>
&lt;hr>
&lt;h1 id="3-أمان-الخيوط-صدمة-التزامن-بلا-خوف">3. أمان الخيوط: صدمة &amp;ldquo;التزامن بلا خوف&amp;rdquo;
&lt;/h1>&lt;p>لطالما كانت البرمجة متعددة الخيوط في C++ محفوفة دائمًا بخطر سباقات البيانات (Data Races) وحالات الجمود (Deadlocks).&lt;/p>
&lt;h2 id="مخاطر-الكائنات-المتبادلة-mutex-وفصل-البيانات-في-c">مخاطر الكائنات المتبادلة (Mutex) وفصل البيانات في C++
&lt;/h2>&lt;p>&lt;code>std::mutex&lt;/code> في C++ هو مجرد أداة للتحكم الحصري في &amp;ldquo;كتلة معينة من التعليمات البرمجية (Critical Section)&amp;quot;، ولا يوجد رابط لغوي بين &amp;ldquo;البيانات المراد حمايتها&amp;rdquo; و &amp;ldquo;الكائن المتبادل (Mutex)&amp;rdquo;.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-cpp" data-lang="cpp">&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;iostream&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;thread&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;mutex&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">#include&lt;/span> &lt;span class="cpf">&amp;lt;vector&amp;gt;&lt;/span>&lt;span class="cp">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="cp">&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">vector&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="kt">int&lt;/span>&lt;span class="o">&amp;gt;&lt;/span> &lt;span class="n">shared_data&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="n">mutex&lt;/span> &lt;span class="n">mtx&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">void&lt;/span> &lt;span class="nf">worker&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="c1">// حتى إذا نسي المطور الحصول على القفل، فسيتم الترجمة بشكل طبيعي
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="c1">// std::lock_guard&amp;lt;std::mutex&amp;gt; lock(mtx);
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span> &lt;span class="n">shared_data&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push_back&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span> &lt;span class="c1">// سباق بيانات قاتل!
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="kt">int&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span> &lt;span class="p">{&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span> &lt;span class="n">t1&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">worker&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">std&lt;/span>&lt;span class="o">::&lt;/span>&lt;span class="kr">thread&lt;/span> &lt;span class="n">t2&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">worker&lt;/span>&lt;span class="p">);&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t1&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="n">t2&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">();&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl"> &lt;span class="k">return&lt;/span> &lt;span class="mi">0&lt;/span>&lt;span class="p">;&lt;/span>
&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="p">}&lt;/span>
&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;h2 id="الكائنات-المتبادلة-mutex-في-rust-تمتلك-البيانات">الكائنات المتبادلة (Mutex) في Rust &amp;ldquo;تمتلك&amp;rdquo; البيانات
&lt;/h2>&lt;p>في Rust، &lt;strong>تغلف (تمتلك)&lt;/strong> &lt;code>Mutex&amp;lt;T&amp;gt;&lt;/code> نوع البيانات المحمي &lt;code>T&lt;/code> باستخدام الأنواع العامة (Generics). للوصول إلى البيانات، يجب عليك استدعاء &lt;code>lock()&lt;/code> للحصول على كائن الحارس (Guard). من المستحيل نحويًا لمس البيانات دون الحصول على القفل.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;span class="lnt">19
&lt;/span>&lt;span class="lnt">20
&lt;/span>&lt;span class="lnt">21
&lt;/span>&lt;span class="lnt">22
&lt;/span>&lt;span class="lnt">23
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">sync&lt;/span>::&lt;span class="p">{&lt;/span>&lt;span class="n">Arc&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Mutex&lt;/span>&lt;span class="p">};&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">thread&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">main&lt;/span>&lt;span class="p">()&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// البيانات مغلفة بالكامل داخل Mutex
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">shared_data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Arc&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">Mutex&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="nb">Vec&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">()));&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">vec!&lt;/span>&lt;span class="p">[];&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">_&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="mi">0&lt;/span>&lt;span class="o">..&lt;/span>&lt;span class="mi">2&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// استنساخ Arc (حساب المراجع الآمن خيطيًا) لمشاركته بين الخيوط
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">data_clone&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Arc&lt;/span>::&lt;span class="n">clone&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="n">shared_data&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">thread&lt;/span>::&lt;span class="n">spawn&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="k">move&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">||&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// لا يمكنك الوصول إلى Vec الداخلي إذا لم تحصل على القفل
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">data_clone&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">lock&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">data&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="mi">1&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">});&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">push&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">in&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">handles&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">handle&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">join&lt;/span>&lt;span class="p">().&lt;/span>&lt;span class="n">unwrap&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>علاوة على ذلك، تمتلك Rust سمتين أساسيتين (Traits) تضمنان أمان المعالجة المتزامنة:&lt;/p>
&lt;ul>
&lt;li>&lt;code>Send&lt;/code>: الأنواع التي يمكن نقل ملكيتها بأمان بين الخيوط&lt;/li>
&lt;li>&lt;code>Sync&lt;/code>: الأنواع التي يكون من الآمن الإشارة إليها (استعارتها) من عدة خيوط في نفس الوقت&lt;/li>
&lt;/ul>
&lt;p>على سبيل المثال، لا ينفذ &lt;code>Rc&amp;lt;T&amp;gt;&lt;/code> غير الآمن خيطيًا السمة &lt;code>Send&lt;/code>. لذلك، إذا حاولت تمريره إلى &lt;code>thread::spawn&lt;/code>، فسيؤدي ذلك فورًا إلى خطأ في الترجمة. بفضل &amp;ldquo;التزامن بلا خوف (Fearless Concurrency)&amp;rdquo; هذا، يتم تحرير المطورين من الخوف من الأخطاء، مما يسمح لهم بدفع عملية الموازاة بقوة أكبر.&lt;/p>
&lt;p>وفقًا لقانون أمدال (Amdahl&amp;rsquo;s Law)، يتم التعبير عن الحد الأقصى للإنتاجية النظرية عند وجود جزء قابل للموازاة $P$ ودرجة التوازي $N$ على النحو التالي:&lt;/p>
$$ S(N) = \frac{1}{(1 - P) + \frac{P}{N}} $$
&lt;p>تسمح Rust بإجراء عمليات إعادة الهيكلة (Refactoring) لتعظيم قيمة $P$ بأمان تام بالاعتماد على نظام الأنواع.&lt;/p>
&lt;div class="mermaid">graph TD
A["أمان الخيوط في C++"] --> B["يعتمد على ذاكرة المطور"]
B --> C["الـ Mutex منفصل عن البيانات"]
C --> D["خطر كبير لحدوث سباقات بيانات صامتة"]
E["أمان الخيوط في Rust"] --> F["السمات Send و Sync"]
F --> G["الـ Mutex يمتلك البيانات"]
G --> H["منع سباقات البيانات في وقت الترجمة"]&lt;/div>
&lt;hr>
&lt;h1 id="4-معالجة-الأخطاء-الاستثناءات-مقابل-أنواع-البيانات-الجبرية">4. معالجة الأخطاء: الاستثناءات مقابل أنواع البيانات الجبرية
&lt;/h1>&lt;p>المعيار لمعالجة الأخطاء في C++ هو &amp;ldquo;الاستثناءات (Exceptions)&amp;rdquo;. ومع ذلك، فإن الاستثناءات تجعل تدفق التحكم غير شفاف، وتسبب عقوبات في الأداء (فك المكدس - Stack Unwinding - وتضخم RTTI). في الأنظمة المدمجة ومحركات الألعاب، غالبًا ما يتم تعطيل الاستثناءات تمامًا (&lt;code>-fno-exceptions&lt;/code>) واعتماد تصميم يعيد رموز الخطأ الكلاسيكية. في C++23، تم إدخال &lt;code>std::expected&lt;/code>، لكن سيستغرق الأمر وقتًا حتى ينتشر في جميع أنحاء النظام البيئي.&lt;/p>
&lt;p>لا يوجد مفهوم للاستثناءات في Rust. يتم إرجاع الأخطاء كـ &amp;ldquo;قيم&amp;rdquo; بحتة، ويتم التعبير عنها بواسطة النوع المعداد (نوع بيانات جبري) &lt;code>Result&amp;lt;T, E&amp;gt;&lt;/code>.&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">fs&lt;/span>::&lt;span class="n">File&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">use&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">std&lt;/span>::&lt;span class="n">io&lt;/span>::&lt;span class="p">{&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Read&lt;/span>&lt;span class="p">};&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c1">// بالنظر إلى نوع القيمة المرجعة فقط، يتضح أنه يمكن أن يحدث خطأ IO
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">read_file_content&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>: &lt;span class="kp">&amp;amp;&lt;/span>&lt;span class="kt">str&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>-&amp;gt; &lt;span class="nb">Result&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="nb">String&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">io&lt;/span>::&lt;span class="n">Error&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="c1">// يؤدي المشغل ? إلى العودة المبكرة (Early return) فورًا في حالة حدوث خطأ، أو يستخرج المحتوى في حالة النجاح
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">File&lt;/span>::&lt;span class="n">open&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">path&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="kd">let&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="o">=&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="nb">String&lt;/span>::&lt;span class="n">new&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">file&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">read_to_string&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="k">mut&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="o">?&lt;/span>&lt;span class="p">;&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="nb">Ok&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">content&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>هذا المشغل &lt;code>?&lt;/code> ثوري. فهو يزيل التداخل العميق (هرم جمل if) الذي يحدث عند فحص رموز الخطأ في C++، ويحافظ على تدفق الشيفرة النظيف تمامًا كاستخدام الاستثناءات، مع السماح لك بوصف صريح لاستدعاءات الدوال التي ستنقل الخطأ.&lt;/p>
&lt;hr>
&lt;h1 id="5-تعدد-الأشكال-polymorphism-من-الدوال-الافتراضية-والقوالب-إلى-السمات">5. تعدد الأشكال (Polymorphism): من الدوال الافتراضية والقوالب إلى السمات
&lt;/h1>&lt;p>يتم تحقيق تعدد الأشكال في C++ بشكل أساسي من خلال وراثة الفئات (Class Inheritance) والإرسال الديناميكي (Dynamic Dispatch) باستخدام الدوال الافتراضية (&lt;code>virtual&lt;/code>)، أو الإرسال الثابت (Static Dispatch) باستخدام القوالب (Templates) (مثل CRTP).&lt;/p>
&lt;p>في الإرسال الديناميكي، يتم تضمين مؤشر (vptr) إلى جدول الدوال الافتراضية (vtable) في الكائن، وتحدث نفقات إضافية لحل المؤشر عند استدعاء الدالة.&lt;/p>
$$ T_{dispatch} = T_{lookup\_in\_vtable} + T_{dereference} $$
&lt;p>تخلت Rust عن &amp;ldquo;وراثة الفئات&amp;rdquo; الكلاسيكية الموجهة للكائنات، واعتمدت بدلاً من ذلك مفهوم &amp;ldquo;&lt;strong>السمات (Traits)&lt;/strong>&amp;rdquo; (تشبه Concept في C++20، لكنها تتمتع بوظائف أكثر).&lt;/p>
&lt;div class="highlight">&lt;div class="chroma">
&lt;table class="lntable">&lt;tr>&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code>&lt;span class="lnt"> 1
&lt;/span>&lt;span class="lnt"> 2
&lt;/span>&lt;span class="lnt"> 3
&lt;/span>&lt;span class="lnt"> 4
&lt;/span>&lt;span class="lnt"> 5
&lt;/span>&lt;span class="lnt"> 6
&lt;/span>&lt;span class="lnt"> 7
&lt;/span>&lt;span class="lnt"> 8
&lt;/span>&lt;span class="lnt"> 9
&lt;/span>&lt;span class="lnt">10
&lt;/span>&lt;span class="lnt">11
&lt;/span>&lt;span class="lnt">12
&lt;/span>&lt;span class="lnt">13
&lt;/span>&lt;span class="lnt">14
&lt;/span>&lt;span class="lnt">15
&lt;/span>&lt;span class="lnt">16
&lt;/span>&lt;span class="lnt">17
&lt;/span>&lt;span class="lnt">18
&lt;/span>&lt;/code>&lt;/pre>&lt;/td>
&lt;td class="lntd">
&lt;pre tabindex="0" class="chroma">&lt;code class="language-rust" data-lang="rust">&lt;span class="line">&lt;span class="cl">&lt;span class="k">trait&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Drawable&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">draw&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">struct&lt;/span> &lt;span class="nc">Circle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">radius&lt;/span>: &lt;span class="kt">f64&lt;/span> &lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="k">impl&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Drawable&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="k">for&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Circle&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">draw&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="o">&amp;amp;&lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="fm">println!&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="s">&amp;#34;Drawing a Circle of radius &lt;/span>&lt;span class="si">{}&lt;/span>&lt;span class="s">&amp;#34;&lt;/span>&lt;span class="p">,&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="bp">self&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">radius&lt;/span>&lt;span class="p">);&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c1">// إرسال ثابت (Static dispatch) (أحادي الشكل - بدون نفقات عامة)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">draw_static&lt;/span>&lt;span class="o">&amp;lt;&lt;/span>&lt;span class="n">T&lt;/span>: &lt;span class="nc">Drawable&lt;/span>&lt;span class="o">&amp;gt;&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">item&lt;/span>: &lt;span class="kp">&amp;amp;&lt;/span>&lt;span class="nc">T&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">draw&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="c1">// إرسال ديناميكي (Dynamic dispatch) (كائن السمة - Trait Object)
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="c1">&lt;/span>&lt;span class="k">fn&lt;/span> &lt;span class="nf">draw_dynamic&lt;/span>&lt;span class="p">(&lt;/span>&lt;span class="n">item&lt;/span>: &lt;span class="kp">&amp;amp;&lt;/span>&lt;span class="nc">dyn&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="n">Drawable&lt;/span>&lt;span class="p">)&lt;/span>&lt;span class="w"> &lt;/span>&lt;span class="p">{&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w"> &lt;/span>&lt;span class="n">item&lt;/span>&lt;span class="p">.&lt;/span>&lt;span class="n">draw&lt;/span>&lt;span class="p">();&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;span class="line">&lt;span class="cl">&lt;span class="w">&lt;/span>&lt;span class="p">}&lt;/span>&lt;span class="w">
&lt;/span>&lt;/span>&lt;/span>&lt;/code>&lt;/pre>&lt;/td>&lt;/tr>&lt;/table>
&lt;/div>
&lt;/div>&lt;p>أهم ما يميز الإرسال الديناميكي في Rust (&lt;code>dyn Trait&lt;/code>) هو أنه لا يمتلك vptr داخل بنية البيانات، بل يستخدم &lt;strong>مؤشرًا سمينًا (Fat Pointer)&lt;/strong>. يحتفظ المؤشر السمين بزوج يتكون من &amp;ldquo;مؤشر إلى البيانات&amp;rdquo; و &amp;ldquo;مؤشر إلى vtable&amp;rdquo;. هذا يجعل من السهل جدًا تنفيذ (أو توسيع) السمات للأنواع المعرفة في المكتبات الخارجية لاحقًا وإرسالها ديناميكيًا.&lt;/p>
&lt;hr>
&lt;h1 id="6-إدارة-الحزم-ونظام-البناء-معاناة-cmake-مقابل-نعم-cargo">6. إدارة الحزم ونظام البناء: معاناة CMake مقابل نِعَم Cargo
&lt;/h1>&lt;p>تعد غياب مدير حزم قياسي أحد أكبر نقاط الضعف في C++. لطالما استنزفت صياغة &lt;code>CMakeLists.txt&lt;/code> الغامضة، وتعقيد حل التبعيات بواسطة &lt;code>find_package&lt;/code>، والاختلافات في مسارات المكتبات باختلاف أنظمة التشغيل، قدرًا هائلاً من وقت مهندسي C++.&lt;/p>
&lt;p>تأتي Rust مزودة بـ &lt;strong>Cargo&lt;/strong> بشكل قياسي، وهو أحد أفضل مديري الحزم وأنظمة البناء في العالم.&lt;/p>
&lt;div class="mermaid">graph TD
A["بيئة البناء في C++"] --> B["CMakeLists.txt"]
B --> C["تكامل vcpkg / Conan"]
C --> D["إنشاء Makefiles / Ninja"]
D --> E["المترجم (GCC/Clang/MSVC)"]
F["بيئة البناء في Rust"] --> G["Cargo.toml"]
G --> H["جلب التبعيات من crates.io"]
H --> I["rustc (بناء Cargo)"]
I --> J["ثنائي جاهز للتشغيل"]&lt;/div>
&lt;p>بمجرد إضافة سطر واحد يحتوي على اسم المكتبة التابعة (Crate) وإصدارها في &lt;code>Cargo.toml&lt;/code>، يتم حل التبعيات المتعدية وتنزيلها وبناؤها بشكل آلي بالكامل. وعلاوة على ذلك، يتم دمج جميع سلاسل الأدوات اللازمة للتطوير - مثل الاختبار (&lt;code>cargo test&lt;/code>)، وتوليد التوثيق (&lt;code>cargo doc&lt;/code>)، والتحليل الثابت (&lt;code>cargo clippy&lt;/code>)، ومنسق الشيفرة (&lt;code>cargo fmt&lt;/code>) - في هذا الأمر الواحد. هذه الراحة قوية لدرجة أنك بمجرد تجربتها، لن ترغب في العودة إلى بيئة بناء C++.&lt;/p>
&lt;hr>
&lt;h1 id="7-عيوب-ومنحنى-التعلم-عند-تعلم-rust">7. عيوب ومنحنى التعلم عند تعلم Rust
&lt;/h1>&lt;p>لقد تحدثت حتى الآن عن مزايا Rust، ولكن بالتأكيد توجد &amp;ldquo;جدران&amp;rdquo; وعيوب سيواجهها مهندس C++ عند وضع Rust موضع التنفيذ الفعلي.&lt;/p>
&lt;h2 id="1-صراع-مرير-مع-مدقق-الاستعارة">1. صراع مرير مع مدقق الاستعارة
&lt;/h2>&lt;p>إذا حاولت تنفيذ هياكل البيانات (مثل القوائم المترابطة ثنائية الاتجاه، وهياكل الرسوم البيانية، والهياكل ذاتية المرجعية، وغيرها) التي كنت تربطها &amp;ldquo;بشكل أو بآخر بمؤشرات خام&amp;rdquo; في C++ بنفس الطريقة في Rust، فلن تجتاز الترجمة بسبب قيود الملكية ودورة الحياة. لإرضاء مدقق الاستعارة، يتعين عليك استخدام تغليف معقد مثل &lt;code>Rc&amp;lt;RefCell&amp;lt;T&amp;gt;&amp;gt;&lt;/code>، أو إعادة التفكير في التصميم من الأساس ليعتمد على مخصصات الساحة (Arena Allocators) أو الإدارة المستندة إلى المؤشرات (Index-based).&lt;/p>
&lt;h2 id="2-طول-وقت-الترجمة">2. طول وقت الترجمة
&lt;/h2>&lt;p>في حين أن بناء C++ يصبح بطيئًا أيضًا بسبب تداخل القوالب (Templates)، إلا أن وقت الترجمة في Rust (خاصة عند البناء النظيف من الصفر - Clean Build) ليس قصيرًا على الإطلاق. وبسبب تزامن مسارات التحسين القوية لـ LLVM، وتوسيع وحدات الماكرو، وأحادية الشكل للأنواع العامة (Monomorphization)، يصبح وقت البناء عنق زجاجة في المشاريع الكبيرة. خلال مرحلة التطوير، من الضروري استخدام حيل مثل الاعتماد الكبير على &lt;code>cargo check&lt;/code>.&lt;/p>
&lt;h2 id="3-قابلية-التشغيل-البيني-مع-قواعد-شيفرة-c-الحالية">3. قابلية التشغيل البيني مع قواعد شيفرة C++ الحالية
&lt;/h2>&lt;p>في حين أن التكامل مع لغة C (عبر FFI) سلس للغاية، إلا أنه من الصعب جدًا ربط Rust مباشرة بقواعد شيفرة C++ الضخمة الحالية (التي تعتمد بشكل كبير على الفئات، والقوالب، والدوال الافتراضية). في السنوات الأخيرة، تطورت أدوات الجسر مثل &lt;code>cxx&lt;/code> و &lt;code>autocxx&lt;/code>، ولكن لا تزال هناك عقبات كبيرة أمام تحقيق انتقال سلس ومثالي.&lt;/p>
&lt;hr>
&lt;h1 id="الخلاصة-هل-يجب-علينا-الانتقال-إلى-rust">الخلاصة: هل يجب علينا الانتقال إلى Rust؟
&lt;/h1>&lt;p>ستستمر C++ في لعب دور مهم في تطوير محركات الألعاب والبنى التحتية الضخمة الحالية. كما أن التحديثات التي أدخلت عبر C++20/23 كانت ملحوظة، مما جعل كتابة الشيفرة أكثر أمانًا من ذي قبل.&lt;/p>
&lt;p>ولكن، بالنسبة لـ &amp;ldquo;مشاريع برمجة النظم الجديدة&amp;rdquo;، أجد الآن أنه &lt;strong>من الصعب إيجاد سبب يمنعنا من اختيار Rust&lt;/strong>. بمجرد اجتياز عملية الترجمة، يتم تحريرك من الخوف من السلوكيات غير المحددة (UB) وتدمير الذاكرة، و&amp;quot;اليقين&amp;rdquo; الذي تقدمه Rust بقدرتها على أداء المعالجة المتزامنة بأمان وبأداء عالٍ يحسن بشكل كبير من النموذج الذهني للمهندس.&lt;/p>
&lt;p>بالنسبة لمهندس C++، لا يقتصر تعلم Rust على مجرد حفظ صياغة جديدة (Syntax)، بل هو تجربة رائعة لاكتساب منظور جديد حول &amp;ldquo;كيفية إدارة الذاكرة والخيوط بشكل آمن&amp;rdquo;. أدعوكم جميعًا لتجربة راحة Cargo وصرامة مدقق الاستعارة بأنفسكم.&lt;/p></description></item></channel></rss>