with - use of virtual function in c++



C++ वर्चुअल फ़ंक्शंस: लिंकर वर्चुअल फंक्शन टेबल में प्रविष्टियों को हटा सकते हैं जिन्हें कॉल नहीं किया जाता है? (1)

यह प्रश्न अप्रयुक्त आभासी कार्यों को खत्म करने के लिए एक तरह का अनुसरण है, जो मेरी रुचि के लिए गहराई से नहीं जाता है

समस्या: वर्चुअल फ़ंक्शन वाले वर्गों को परिभाषित करते समय, कंपाइलर वर्चुअल फ़ंक्शन तालिका के लिए संग्रहण को आवंटित करता है, और तालिका में कार्य करने के लिए पॉइंटर्स को स्टोर करता है। इससे लिंकर उन कार्यों का कोड रखता है, भले ही वे कभी भी कॉल किए गए हों। संभवत: निष्पादन योग्य में बहुत से मृत कोड बनाए जा सकते हैं, भले ही कंपाइलर ऑप्टिमाइज़ेशन सेटिंग्स मृत कोड के उन्मूलन की मांग करें।

अब, अगर निष्पादन योग्य में कहीं नहीं एक विशेष वर्चुअल फ़ंक्शन (या, दूसरे शब्दों में, आभासी फ़ंक्शन तालिका के संबंधित स्लॉट तक पहुंच) की कॉल है, तो संबंधित फ़ंक्शन पॉइंटर वर्चुअल फ़ंक्शन तालिका से छोड़ा जा सकता है, और लिंकर फ़ंक्शन के कोड को निकाल देगा, अन्य संहिताओं की संभव आगे की कमी जो अनुपलब्ध हो जाता है

स्पष्ट रूप से, यह कंपाइलर द्वारा नहीं किया जा सकता, क्योंकि यह केवल लिंक समय पर स्पष्ट हो जाता है कि क्या किसी विशिष्ट आभासी फ़ंक्शन को कहा जाता है (स्थिर लिंकिंग संभालने - यह स्पष्ट है कि इसे डायनेमिक लिंकिंग के साथ नहीं किया जा सकता है)। मैं लिंकर्स के साथ काफी परिचित नहीं हूं ताकि यह बता सकूं कि कंपाइलर ऐसे आभासी फ़ंक्शन तालिकाओं को ऐसे तरीके से फेंक सकता है कि लिंकर तालिका में व्यक्तिगत अप्रयुक्त प्रविष्टियों को चुनने से दूर कर सकता है।

असल में, मेरी ट्रेन की सोची यह है: वर्चुअल फ़ंक्शन तालिका में फ़ंक्शन पॉइंटर फंक्शन के लिए एक संदर्भ है, जो यह निर्धारित करने के लिए उपयोग करता है कि फंक्शन के कोड को एक्जीक्यूटेबल में बनाए रखा जाना चाहिए। इसी तरह, एक आभासी फ़ंक्शन कॉल सभी आभासी फ़ंक्शन तालिकाओं में एक विशेष स्लॉट का एक संदर्भ होता है, जो वर्ग से प्राप्त होता है जिसका वर्चुअल फ़ंक्शन कॉल हो रहा है। क्या इस प्रकार के संदर्भ को लिंकर को ऐसे तरीके से भेजी जा सकता है कि यह एक वर्चुअल फंक्शन टेबल स्लॉट को दूर कर सकता है जब इसके शून्य संदर्भ होते हैं?

ध्यान दें कि यह एक समान कॉल के साथ वर्चुअल फंक्शन कॉल की जगह नहीं है, जब संकलक कंपाइल समय पर कॉल लक्ष्य निर्धारित कर सकता है। मुझे पता है कि कुछ कंपलर ऐसा कर सकते हैं, लेकिन यह एक अलग मामला है क्योंकि फ़ंक्शन वास्तव में बुलाया जाता है, और यह आभासी फ़ंक्शन डिस्पैच का ओवरहेड है जो हटाया जाता है। मेरे मामले में मैं चाहता हूं कि पूरे कोड को फ़ंक्शन के लिए निकाल दिया जाए जिसे नहीं कहा जाता है।

यदि सभी वर्ग परिभाषाओं पर मेरा नियंत्रण था, तो मैं उन सभी आभासी कार्यों को मैन्युअल रूप से समाप्त कर सकता हूं जिन्हें नहीं कहा जाता है। लेकिन पुस्तकालयों का उपयोग करते समय यह अवास्तविक है

क्या ऐसा कुछ है जो "लिंक समय अनुकूलन" या "संपूर्ण प्रोग्राम अनुकूलन" के साथ किया जा सकता है? वहाँ compilers जो सफलतापूर्वक ऐसा कर रहे हैं?


मृत कोड के साथ समस्या यह है कि संकलक संभवतया यह सुनिश्चित नहीं कर सकता है कि कोड गतिशील पुस्तकालयों के परिप्रेक्ष्य से मर गया है। एक एक्जीक्यूटेबल गतिशील रूप से एक लाइब्रेरी को शामिल कर सकता है जो मृत कोड का उपयोग करता है (मृत कोड वाले वर्गों से प्राप्त होता है)

इसके अतिरिक्त, लिंक-टाइम के दौरान वी-टेबल की संरचना को बदलने से पूरी तरह से ठीक हो सकता है यदि निष्पादन योग्य फ़ंक्शन कॉल करने वाला केवल एक है। हालांकि, यदि कोई डायनेमिक लाइब्रेरी कोई कॉल करता है, तो उसे वी-टेबल की एक अलग समझ होगी और यह गलत फ़ंक्शन को बुलाएगा।

इन तथ्यों के कारण, और अंकित मूल्य पर अधिक (यदि कोई हो) प्रदर्शन प्राप्त नहीं किया जाता है, तो लिंकरों का अनुकूलन करने के लिए यह सुविधा बहुत कम होने की संभावना नहीं है।

वर्चुअल फ़ंक्शन का डी-वर्चुअलाइज़ेशन वास्तव में इस से संबंधित है, और सुरक्षित ऑप्टिमाइज़िंग लिंकर्स फ़ंक्शन कॉल्स की बहुत छोटी संख्या को केवल डी-वर्चुअलाइज कर सकते हैं। उदाहरण के लिए, यह फ़ंक्शन को केवल वर्चुअलाइज्ड कर सकता है अगर यह गारंटी दे सकता है कि कोई गतिशील लायब्रेरी कॉलस्टैक में कोई भी भाग नहीं खेल सकती है।

संपादित करें @ क्यूरगिग्यू ने एक ऐसा मामला उठाया है जहां कंपाइलर अनुकूलन के साथ थोड़ी अधिक उदारवादी बन सकता है, और जब लिंकर जान सकता है कि कोई बाहरी कोड कक्षा के बारे में नहीं जानता है। इसका एक उदाहरण फ़ाइल स्कोप के साथ एक क्लास है।





dead-code