मैंने यह लघु कार्यक्रम लिखा कि यह देखने के लिए कि कैसे devirtualization काम करेगा। संकलक सही प्रकार अनुमान में सक्षम होना चाहिए:कंपाइलर devirtualization, बहुत स्मार्ट नहीं है?
#include <iostream>
using std::cout;
using std::endl;
class Base
{
public:
void foo() { cout << "Base::foo" << endl; }
virtual void bar() { cout << "Base::bar" << endl; }
virtual ~Base() = default;
};
class Child : public Base
{
public:
void foo() { cout << "Child::foo" << endl; }
void bar() { cout << "Child::bar" << endl; }
};
int main()
{
Base* obj = new Child;
obj->foo();
obj->bar();
delete obj;
}
https://gcc.godbolt.org/ के माध्यम से जीसीसी 5.3 और बजना 3.7 का उपयोग कर -O2 -std=c++11
साथ संकलित।
क्या पता चला कि न तो संकलक सब कुछ को अनुकूलित कर सका है - जीसीसी inlines foo()
और bar()
करने के लिए आभासी कॉल करता है, जबकि बजना foo()
करने के लिए कॉल करता है और devirtualizes और inlines bar()
को कहते हैं।
इस बीच, अगर बजाय मैं obj->bar();
और फिर obj->foo();
फोन, compilers के अनुकूलन में कोई समस्या नहीं है - बजना दोनों कॉल inlines और जीसीसी के बजाय आभासी एक और inlines foo()
की bar()
करने के लिए सामान्य कॉल करता है।
क्या कोई इस व्यवहार को समझा सकता है?
इस सवाल का अजीब है। हमें क्या जवाब देना चाहिए? जीसीसी क्लेंग से भी बदतर है? कुछ समय कंपाइलर सामान को चित्रित कर सकते हैं, कभी-कभी वे याद करते हैं। क्लैंग नया है और इस तरह के अनुकूलन का समर्थन करने के लिए स्क्रैच से बनाया गया था। –
नहीं, अगर मैं गैर-आभासी कॉल पहले किया जाता है, तो इस मामले में इस खराब अनुकूलन से परे कुछ खास है, तो मैं सिर्फ उत्सुक हूं। कुछ अनुकूलन पहले से ही प्रदर्शन कर रहे हैं जो devirtualization परेशान? – cailinscath
http://hubicka.blogspot.de/2014/04/devirtualization-in-c-part-5-feedback.html जीसीसी के लिए दिलचस्प पृष्ठभूमि जानकारी प्रदान करता है। यह जीसीसी डेवलपर से devirtualization के बारे में लेखों की एक पूरी गंभीर है जो इसे लागू किया। क्या आपने gcc में "-fwhole-program" या "-fsuggest-final-विधियां" जोड़ने का प्रयास किया है? – Jens