HeadlinesBriefing favicon HeadlinesBriefing.com

تصوير Vtables Rust: كيف يعمل dyn Trait في الذاكرة

Hacker News •
×

أنا أستكشف Rust وهي كلا من مرضية ومحيرة في الوقت نفسه. حتى الآن، أنا أتعلم من الكتاب وكتاب Mara Bos، لكن لدي رغبة في dissecting بنفسي. كان هدفي الأول لهذه التجارب مقارنة نهج Rust في التعددية مع نهج C++. ومع ذلك، كما أدركت، فهي فخ إلى حد ما عندما نحاول فهم لغة جديدة من خلال لغة أخرى لمحاولةDrawing parallels 1:1. قد يبدو أنه يساعد، لكن في نهاية المطاف، لا يمكننا معاملة Rust كأنها C++ بسينتاكس مختلفة. لو كان الأمر كذلك، لما كان هناك شيء ثوري. gesagt، أنا أعتقد أن هناك قيمة في الحفر وفهم لماذا. لذا، إذا كنت مثلي وتريد معرفة بالضبط ما يحدث في الذاكرة، من أجل الشعور بأنك حقاً تفهم المفاهيم، فآمل أن تجد هذه المشاركة مفيدة :)بجانب ذلك، الصورة المصغرة هي صورة لفطريات الرطوبة، التي ن owe اسم Rust إليها. Credit: gailhampshire from Cradley, Malvern, U.K, CC BY 2.0, via Wikimedia Commons. يمكنك العثور على كل الكود والتجارب على Git Hub.

المقدمة: جوهر الموضوع

ما نحاول تحقيقه بسيط جداً. لنفترض أننا لدينا مجموعة من الأشكال: دوائر، ومربعات، وثلاثيات، ونريد استدعاء draw() على كل واحدة.

طريقة C++ #1: الدوال الافتراضية الطريقة الأولى التي تخطر على بال في C++ للقيام بهذا هي من خلال الدوال الافتراضية، التي تستخدم التعددية في وقت التشغيل. مؤشر جدول الجداول الافتراضية (vtable) resides inside the object, virtual dispatch happens automatically.

std::vector<Shape*> shapes = { new Circle(), new Square() };

for (auto* s : shapes)s->draw();

المثيل لـ Rust هو dyn Trait، وهو ما نريد في النهاية فهمه. ولكن أولاً، دعونا نلقي نظرة على طريقة أخرى يمكننا من خلالها حل هذه المسألة في C++.

طريقة C++ #2: CRTP يمكن أيضاً أن يأخذ المرء طريق CRTP (النمط المتكرر الفضولي للTemplates)، وهو essentially تعددية في وقت الترجمة. إذا كنت مهتماً، فهذه الحلقة الدراسية الرائعة Klaus Iglberger كانت Introductionsي الأولى إلى الموضوع، وأنا أعود إليها للمرجع.

template<typename Derived>struct Shape {void draw() {static_cast<Derived*>(this)->draw();}}; Basically، لا توجد جداول افتراضية ويتم حلها في وقت الترجمة، sacrifying قابلية القراءة (إنه حقاً فم ملئ).

Rust يقدم بديلاً أكثر مباشرة وبساطة لـ CRTP، ألا وهي singleta. هذه هي المنهجية التي سنحفرها أولاً لبدء بناء نموذجنا العقلي لما يقدمه Rust.

إرسال ثابت Photo by Jiawei Zhao on Unsplash الإرسال الثابت، والمعروف أيضاً باسم التعاميم، يحقق نتيجة مشابهة لـ CRTP: يقوم المجمع بإنشاء نسخة منفصلة من الدالة لكل نوع يتم استدعاؤه معه. لا يوجد تكلفة في وقت التشغيل، لكن الأنواع يجب أن تكون معروفة في وقت الترجمة.

trait Draw {fn draw(&self) -> &str;}struct Circle;struct Square;impl Draw for Circle {fn draw(&self) -> &str {