هل يتم تحديد الوظائف في الرؤوس المضمنة؟

StackOverflow https://stackoverflow.com/questions/2391294

  •  25-09-2019
  •  | 
  •  

سؤال

إذا قمت بتحديد وظيفة غير عضو في رأس ، فهل سيتم صياغتها دائمًا من قبل المترجم ، أم هل يختار المترجم بناءً على أساليب الاستدلال؟ أعلم أن __inline مجرد تلميح ، هل هو نفسه مع الوظائف في الرؤوس؟

هل كانت مفيدة؟

المحلول

تذكر أن تضمين شيء من الرأس لا يختلف عن مجرد كتابته مباشرة في الملف المصدر. لذا فإن كونك في رأس لا يحدث فرقًا فيما يتعلق بالمترجم ؛ لم يكن يعلم أنه كان هناك.

لذلك عندما تحدد وظيفة في ملف رأس ، وتضمين ملف الرأس هذا في ملف ، يبدو أنك كتبت الوظيفة مباشرة في الملف. والآن والسؤال هو ، "هل يختار المترجم مضمون الأشياء بناءً على الاستدلال؟"

الجواب هو "يعتمد على المترجم". لا تقدم المعيار أي ضمانات حول ما يتم توضيحه أم لا. ومع ذلك ، فإن أي مترجم حديث سيكون ذكيًا للغاية بشأن ما يدومه ، على الأرجح مع الاستدلال.

ومع ذلك ، وصلنا إلى نقطة مثيرة للاهتمام. تخيل أن لديك وظيفة في رأس وتشمل هذا الرأس في ملفات مصدر متعددة. سيكون لديك بعد ذلك تعريفات متعددة للوظيفة ، عبر وحدات الترجمة ، وهذا ينتهك قاعدة التعريف الواحد. Ergo ، سوف تحصل على أخطاء ترجمة. (عادة ما يكون خطأ الرابط شيءًا على غرار: "خطأ ، الوظيفة X المحددة بالفعل في Y") ما يمكنك فعله هو استخدام inline الكلمة الرئيسية ولم تعد تنتهك ODR.

بالمناسبة __inline غير قياسي. على عكس رسالتك ، فإنه عادة ما يكون امتدادًا للمترجم القوات inlining ، لا يلمح ذلك. inline هي الكلمة الرئيسية القياسية ، والتي كانت تهدف في الأصل إلى تلميح إلى وضع الإضافات. كما تقول ، فإن معظم المجمعين الحديثين يتجاهلونه تمامًا في هذا الصدد ، وهناك الغرض الوحيد في الوقت الحاضر هو إعطاء الأشياء الداخلية.

نصائح أخرى

من C ++ الأسئلة الشائعة لايت:

بغض النظر عن كيفية تعيين وظيفة على أنها مضمّنة ، فمن طلب أن يسمح للمترجم بالتجاهل: قد يكون هناك بعض المكالمات أو أي شيء من المكالمات إلى وظيفة مضمنة.

وسوف تختار على أساس الاستدلال. تأكد من إعلانه على أنه مضمّن بشكل صريح وإلا قد تحصل على خطأ في ارتباط الرمز المكرر إذا قمت بتضمين الرأس في أكثر من وحدة تجميع واحدة.

اذا أنت حدد وظيفة ذات ارتباط خارجي في ملف رأس وتضمينها في أكثر من وحدة ترجمة واحدة ، ستحصل على خطأ في التجميع (بشكل أدق: Linker ERORR) لانتهاك قاعدة تعريف واحدة (ODR). لذا فإن الإجابة هي "لا": لن يتم تحديد دالة في ملف الرأس بواسطة برنامج التحويل البرمجي باعتباره تلميحًا في الإطار ولن يعذرك من مراقبة متطلبات ODR. ليس فقط هذه الوظائف ليست مضمونة فقط ، ولكن على الأرجح لن يتم تجميع البرنامج الخاص بك.

من أجل تحديد وظيفة في ملف رأس والابتعاد عنه ، عليك إما أن تمنحها ارتباطًا داخليًا (أعلن ذلك static, وينتهي به الأمر بوظيفة منفصلة في كل وحدة ترجمة) ، أو إعلانها صراحة inline.

أما بالنسبة للاستدلال ... فإن المجمعين الحديثين عادة ما ينظرون فعليًا في أي وظيفة لتحديد (من خلال تطبيق الاستدلال) ، بغض النظر عن مكان تعريفه وما إذا كان يتم الإعلان عنه صراحة inline أم لا.

لا يوجد سحر حول الوظائف في الرؤوس. لا يعرف المترجم حتى ما إذا كانت الوظيفة محددة في رأس أم لا. (نظرًا لأن الرؤوس فعليًا مجرد نسخ/لصق في الملف المصدر ، يمكنك تحديده في رأس ، لكن المترجم يراه فقط كجزء من وحدة الترجمة)

هناك أيضًا معنيان مختلفان لـ "مضمّن" لتكون على دراية:

قد تكون الوظيفة مضمون كما هو محدد بواسطة معيار C ++: يتم ذلك إما عن طريق بادئة الوظيفة مع inline الكلمة الرئيسية ، أو إذا كانت وظيفة عضو ، من خلال تحديدها داخل تعريف الفئة.

تأثير هذا هو

  • أبلغ الرابط بأنه قد يواجه تعريف الوظيفة في ملفات متعددة ، ويجب أن يجمعها بصمت معًا بدلاً من إلقاء خطأ
  • اجعل من السهل على المترجم أداء الإضفاء الاقوي.

الإطالة الاقوي من ناحية أخرى ، هو ببساطة فعل استبدال استدعاء الوظيفة من قبل جسم الوظيفة المدعومة ، مما يعني أن هذا التحسين يتم تطبيقه فعليًا على مواقع الاتصال ، وليس للوظائف. يمكن أن تسمى الوظيفة عادة بعض الأماكن ، ولكنها مضمّنة في مكان آخر. يتم تحديد مكالمة الوظيفة عندما يشعر المترجم وكأنه ، ومن الأفضل فصلها تمامًا عن المعنى الأول "المضمّن".

سيقوم المترجم بتطبيق التحسين المضمون إذا ومتى وأين يبدو الأمر. ويستخدم الكثير من الاستدلال لهذا. من المرجح أن تكون الوظائف الأصغر محصورة. إذا قرر أنه سيتم تنفيذ موقع اتصال معين في كثير من الأحيان بما فيه الكفاية ، فمن الأرجح أن يتم ضمه. في نهاية المطاف ، تعتمد الاستدلال الذي يستخدمه على "هل سيحسن الأداء أو تدهوره". وهو عمومًا قاضٍ أفضل في هذا البشر ، لذلك لا تحتاج حقًا إلى معرفة ما هي الاستدلال الدقيق الذي تستخدمه. إن إطار الكثير من الأداء فقط سيضر بالأداء.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top