2015-09-01 6 views
6

एक परियोजना है, जिसमें तरह एक इंटरफ़ेस वर्ग है कल्पना कीजिए निम्नलिखित:एक vtable में डुप्लिकेट फ़ंक्शन क्यों नहीं हो सकते हैं?

struct Interface 
{ 
    virtual void f()=0; 
    virtual void g()=0; 
    virtual void h()=0; 
}; 

मान लीजिए कि कहीं और, किसी एक वर्ग इस इंटरफेस को लागू है, जिसके लिए f, g, h सभी एक ही काम करते हैं बनाने के लिए चाहता है ।

struct S : Interface 
{ 
    virtual void f() {} 
    virtual void g() {f();} 
    virtual void h() {f();} 
}; 

तो यह S जिसकी प्रविष्टियों S::f करने के लिए सभी संकेत दिए गए हैं के लिए एक vtable उत्पन्न करने के लिए, इस प्रकार रैपिंग कार्यों g और h के लिए एक कॉल की बचत एक वैध अनुकूलन होगा।

vtable की सामग्री मुद्रण, हालांकि, पता चलता है कि इस अनुकूलन नहीं किया जाता है:

S s; 
void **vtable = *(void***)(&s); /* I'm sorry. */ 
for (int i = 0; i < 3; i++) 
    std::cout << vtable[i] << '\n'; 

0x400940
0x400950
0x400970

साथ -O3 या -Os नहीं है संकलन प्रभाव, जैसा कि क्लैंग और जीसीसी के बीच स्विचिंग करता है।

यह अनुकूलन अवसर क्यों चूक गया है?

फिलहाल, इन अनुमान है कि मैं पर विचार किया है (और अस्वीकार कर दिया) कर रहे हैं:

  1. vtable मुद्रण कोड वास्तव में कचरा प्रिंट करता है।
  2. प्रदर्शन सुधार बेकार माना जाता है।
  3. एबीआई इसे प्रतिबंधित करता है। क्योंकि ...

    // somewhere-in-another-galaxy.hpp 
    struct X : S { 
        virtual void f(); 
    }; 
    
    // somewhere-in-another-galaxy.cpp 
    include <iostream> 
    void X::f() { 
        std::cout << "Hi from a galaxy far, far away! "; 
    } 
    

    एक संकलक आपका अनुकूलन लागू करता है यदि यह कोड काम नहीं होगा

+8

यह अनुकूलन कोड अनुरूप करने के लिए दृश्यमान होगा, क्योंकि सदस्य कार्यों के पॉइंटर्स बराबर की तुलना करेंगे। –

+0

यह मूर्खतापूर्ण प्रतीत हो सकता है, लेकिन मेरे लिए, * फ़ंक्शन कॉलिंग 'f' *' f' ही नहीं है। तो यह अजीब होगा, अगर सदस्य कार्यों के पॉइंटर्स बराबर होंगे, तो आपको नहीं लगता? –

+2

@ डेविड श्वार्टज़: llvm फ़ंक्शन पॉइंटर्स के माध्यम से इनलाइन कोड जैसी चीजों को करने में सक्षम होने के लिए जाना जाता है। संभवतः यह 'जी' के शरीर को 'जी' और 'एच' में भी रेखांकित कर सकता है? ओपी द्वारा अनुमानित अनुकूलन के समान नहीं है ... मेरा अनुमान है कि यह अनुकूलन अभ्यास में बहुत महत्वपूर्ण नहीं है, इसलिए कोई भी परवाह नहीं करता है? ऐसा लगता है कि बराबर समस्या की तुलना में "पॉइंटर-टू-सदस्य-फ़ंक्शन" या तो संकलक द्वारा पता लगाया जा सकता है, या मानक को संशोधित करने के लिए संशोधित किया जा सकता है, वैसे भी ऑप्टिमाइज़ेशन को अनुमति देने के लिए अनुमति दी जाती है, जिसकी प्रतिलिपि की अनुमति है –

उत्तर

2

इस तरह के अनुकूलन मान्य नहीं है।

Interface* object = new X; 
object->g(); 

मेरे अनुवाद इकाई का एक संकलक अपनी कक्षा आंतरिक कार्यान्वयन के बारे में पता नहीं है तो ग्राम() और ज() यह सिर्फ VFT 'अपने वर्ग के संबंधित प्रविष्टियों के लिए आभासी कार्यों तालिका संदर्भ' मेरी कक्षा में डालता है के लिए ।

+0

समस्या इतना नहीं है "आपका कंपाइलर मेरे वर्ग-आंतरिक कार्यान्वयन के बारे में नहीं जानता" - भले ही ' जी() 'हेडर में लागू किया गया है, यह एक अन्य मामला है" अन्य कंपाइलरों को मेरे कंपाइलर के अनुकूलन को वैध बनाने के लिए जारी रखने की आवश्यकता नहीं है "(जो कि 'एफ' ओवरराइड करते समय' जी 'ओवरराइड करके कर सकता है)। – PBS

+1

एक और नोट: जब किसी अज्ञात नेमस्पेस में 'S' की परिभाषा को लपेटना और '-O2' चालू करना, gcc * करता है * सभी vtable प्रविष्टियों को मर्ज करता है (इस प्रकार इस उत्तर में विश्वास प्रदान करता है)। – PBS

संबंधित मुद्दे