سؤال

بالأمس وجدت نفسي أكتب كودًا مثل هذا:

SomeStruct getSomeStruct()
{
    SomeStruct input;

    cin >> input.x;
    cin >> input.y;
}

بالطبع نسيت إعادة البنية التي أنشأتها للتو.ومن الغريب أن القيم الموجودة في البنية كان تمت تهيئة هذه الوظيفة التي تم إرجاعها إلى الصفر (عند تجميعها باستخدام g++).هل هذه مجرد صدفة أم أنه تم إنشاء SomeStruct آخر وتهيئته في مكان ما ضمنيًا؟

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

المحلول

<اقتباس فقرة>   

هل SomeStruct آخر الحصول على إنشاء وتهيئة مكان ضمنا؟

ونفكر في كيفية يتم إرجاع البنية. إذا كان كل من x وy هي 32 بت، أنها كبيرة جدا لاحتوائه في سجل على الهندسة المعمارية 32 بت، والأمر نفسه ينطبق على قيم 64 بت على معمارية 64 بت (الجوابDenton طبقة النبلاء وتذكر كيف هي قيم أبسط عاد)، لذلك لا بد من تخصيص مكان ما. وسيكون من الإسراف في استخدام كومة لهذا، لذلك لابد من تخصيص على المكدس. ولكن لا يمكن أن يكون على الإطار كومة من وظيفة getSomeStruct الخاص بك، لأن ذلك لا يصح بعد الآن بعد عودة وظيفة.

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

وهناك تحسينات أيضا مثل "القيمة المسماة الأمثل العودة" حيث نسخ إضافية يمكن elided. لذلك، كان عليك استخدام return في عداد المفقودين، ستنشأ نتيجة مباشرة على المساحة المخصصة من قبل المتصل، بدلا من إنشاء مؤقتة ونسخها.

لمعرفة المزيد حول ما يحدث، لا بد من النظر في وظيفة المتصل. هل هو تهيئة (من الصفر) وSomeStruct "فارغة" التي لاحقا تعيين القيمة عودة وظيفة getSomeStruct الخاصة بك؟ أم أنها تفعل شيئا آخر؟

نصائح أخرى

وتقع قبالة نهاية الدالة التي يتم أعلنت لإرجاع قيمة (دون الرجوع صراحة قيمة) يؤدي إلى عواقب غير محددة. لدول مجلس التعاون الخليجي، يجب أن تبدأ مع تبديل سطر الأوامر -Wall أن يتحول في معظم التحذيرات المفيدة. تحذير دول مجلس التعاون الخليجي المحددة التي تسيطر على تحذير تريده هو -Wreturn-type (والتي يتم تضمينها في -Wall، أنا فقط أذكر هذا للتأكد من اكتمالها).

وبمجرد الانتهاء من التحذيرات قيد التشغيل، يجب عليك أيضا استخدام -Werror لعلاج تحذيرات أنها أخطاء وجعل وقف بناء عند نقطة يكشف خطأ.

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

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

ومما يؤسف له حتى تغيير تافهة لوظيفة يمكن أن يسبب تخصيص السجل لتغيير، وبالتالي فإن قيمة الإرجاع يصبح القمامة الحقيقية.

أجد هذا مثيرا للاهتمام.مع استخدام الخيارات الافتراضية، يكون لدى المترجمين التاليين السلوك التالي عند تجميع ملف GetSomeStruct() وظيفة:

  • Microsoft VC، جميع الإصدارات (منذ VC6 على أي حال):

    error C4716: 'getSomeStruct' : must return a value

  • المريخ الرقمي:

    Warning 18: implied return of getSomeStruct at closing '}' does not return value

  • كومو:

    warning: missing return statement at end of non-void function "getSomeStruct"

  • مجلس التعاون الخليجي:

    لا خطأ أو تحذير

بالنظر إلى الجملتين التاليتين من المعيار (6.6.3 الفقرة 2):

بيان إرجاع بدون يمكن استخدام التعبير فقط في الوظائف التي لا ترجع قيمة ، وهذا هو ، وظيفة مع العودة اكتب void أو منشئ (12.1) أو ملف المدمر (12.4)....تتدفق قبالة نهاية الدالة تكافئ عائد بدون قيمة ؛هذه النتائج في سلوك غير معرف في وظيفة إرجاع القيمة.

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

وبالنسبة لي المترجم لم تسمح بذلك: http://codepad.org/KkzVCesh

وأنت لم تحصل على أي تحذير لأنك لم يكن لديك -Wall -Werror قيد التشغيل. (كما ورد في إجابات أخرى)

ولكن أعتقد أنك ربما حصلت على البنية شغل الصفر نتيجة لأن الكائن كومة كان الافتراضية التي شيدت في وظيفة المتصل، وربما مع الحجج الصفر واضحة، وإلا بسبب الأصفار على المكدس؟

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