2013-02-07 7 views
15

मान लीजिए मैं निम्नलिखित कोडक्या सी ++ कंपाइलर एक ही पॉइंटर पर दोहराए गए आभासी फ़ंक्शन कॉल को अनुकूलित कर सकते हैं?

void f(PolymorphicType *p) 
{ 
    for (int i = 0; i < 1000; ++i) 
    { 
     p->virtualMethod(something); 
    } 
} 

संकलक की भिन्नता कोड उत्पन्न होगा p के virtualMethod 1 या 1000 बार vtable प्रवेश? मैं माइक्रोसॉफ्ट के कंपाइलर का उपयोग कर रहा हूँ।

संपादित

यहाँ वास्तविक दुनिया मामले मैं देख रहा हूँ के लिए उत्पन्न विधानसभा है। line->addPoint() चिंता का आभासी तरीका है। मेरे पास कोई असेंबली अनुभव नहीं है, इसलिए मैं धीरे-धीरे इस पर जा रहा हूं ...

; 369 :  for (int i = 0; i < numPts; ++i) 

    test ebx, ebx 
    je SHORT [email protected]_SCANNE 
    lea edi, DWORD PTR [ecx+32] 
    npad 2 
$L[email protected]_SCANNE: 

; 370 :  { 
; 371 :   double *pts = pPoints[i].SystemXYZ; 
; 372 :   line->addPoint(pts[0], pts[1], pts[2]); 

    fld QWORD PTR [edi+8] 
    mov eax, DWORD PTR [esi] 
    mov edx, DWORD PTR [eax+16] 
    sub esp, 24     ; 00000018H 
    fstp QWORD PTR [esp+16] 
    mov ecx, esi 
    fld QWORD PTR [edi] 
    fstp QWORD PTR [esp+8] 
    fld QWORD PTR [edi-8] 
    fstp QWORD PTR [esp] 
    call edx 
    add edi, 96     ; 00000060H 
    dec ebx 
    jne SHORT [email protected]_SCANNE 
[email protected]_SCANNE: 

; 365 :  } 
+5

संकलक पूछो कोडांतरक कोड उत्पन्न करने के लिए पूर्ण अनुकूलन और पूरे कार्यक्रम अनुकूलन के साथ VS2012 इस कार्यक्रम को संकलित करता है और जाँच करें। –

+1

इसे अनुकूलन के साथ संकलित करें और परिणामी जेनरेट कोड देखें। – Petesh

+3

जोआचिम की टिप्पणी में जोड़ने के लिए - * जांच के अलावा अन्य खोजने के लिए कोई अन्य तरीका नहीं है। –

उत्तर

5

सामान्यतः, नहीं, यह संभव नहीं है। फ़ंक्शन *this को नष्ट कर सकता है और प्लेसमेंट-नई उस ऑब्जेक्ट को उसी स्थान से उसी आधार से निकाला जा सकता है।

संपादित करें: यहां तक ​​कि आसान, फ़ंक्शन p बदल सकता है। संकलक संभवतया नहीं जानता कि p का पता कौन है, जब तक यह प्रश्न में अनुकूलन इकाई के लिए स्थानीय न हो।

2

सामान्य रूप से असंभव है, लेकिन विशेष मामले हैं जिन्हें विशेष रूप से अंतर-प्रक्रियात्मक विश्लेषण के साथ अनुकूलित किया जा सकता है।

#include <iostream> 

using namespace std; 

namespace { 
struct A { 
    virtual void foo() { cout << "A::foo\n"; } 
}; 

struct B : public A { 
    virtual void foo() { cout << "B::foo\n"; } 
}; 

void test(A& a) { 
    for (int i = 0; i < 100; ++i) 
    a.foo(); 
} 
} 

int main() { 
    B b; 
    test(b); 
} 

लिए:

01251221 mov   esi,64h 
01251226 jmp   main+10h (01251230h) 
01251228 lea   esp,[esp] 
0125122F nop 
01251230 mov   ecx,dword ptr ds:[1253044h] 
01251236 mov   edx,12531ACh 
0125123B call  std::operator<<<std::char_traits<char> > (012516B0h) 
01251240 dec   esi 
01251241 jne   main+10h (01251230h) 

तो यह प्रभावी ढंग से करने के लिए लूप अनुरूप होता है:

for(int i = 0; i < 100; ++i) 
    cout << "B::foo()\n"; 
+0

प्लस 1, जो 'असंभव' अक्सर तुच्छ संभव रूप से संभव बनाता है। –

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