التحميل الزائد << المشغل والعودة
-
23-09-2019 - |
سؤال
جربت الرمز التالي:
#include <iostream>
using std::cout;
using std::ostream;
class X
{
public:
friend ostream& operator<<(ostream &os, const X& obj)
{
cout << "hehe"; // comment this and infinite loop is gone
return (os << obj);
}
};
int main()
{
X x;
cout << x;
return 0;
}
عندما أقوم بتجميع هذا ، فهو كما هو متوقع ؛ حلقة لانهائي. إذا قمت بإزالة cout
بيان داخل وظيفة الصديق ، لا يحدث التكرار. لماذا هو كذلك؟
المحلول
يقرر Optimizer أن كل نشاطك المتبقي ليس له أي تأثير ويقوم بتحسينه بعيدًا. سواء كان الأمر صحيحًا أو خطأ أمر مختلف.
خاصه:
X x;
يخلق كائن فارغ "x"
cout << x;
المكالمات:
return (os << obj);
وهو إلحاق كائن فارغ ؛ يلاحظ برنامج التحويل البرمجي "OS" أي شيء منذ آخر مكالمة ولا يظهر أي وعد في القيام بذلك أكثر (ولا شيء آخر يحدث) ، لذلك يقرر أن النشاط التجاري بأكمله لا لزوم له ويمكن اقتطاعه في هذه المرحلة.
في حالة الاتصال
cout << "hehe"; // comment this and infinite loop is gone
هناك بعض النشاط الإضافي بحيث لا يزيل المُحسّن المكالمة التالية.
أعتقد أنه إذا تم تهيئته x
مع أي شيء غير فارغ ، أو أجرى أي نشاط غير فائق بخلاف cout << "hehe";
, ، سيكون لديك عودة تعمل بنفس الشيء.
نصائح أخرى
في كلتا الحالتين (مع وبدون كتابة "Hehe") Visual Studio 2005 يعطي التحذير التالي:
warning C4717: 'operator<<' : recursive on all control paths, function will cause runtime stack overflow
في كلتا الحالتين ، يجمع وفي كلتا الحالتين فائض مكدس.
ومع ذلك ، بدون "Hehe" ، يحدث فائض المكدس في وقت أقرب قليلاً.