Suppose I have the following code
void f(PolymorphicType *p)
{
    for (int i = 0; i < 1000; ++i)
    {
        p->virtualMethod(something);
    }
}
Will the compiler's generated code dereference p's vtable entry for virtualMethod 1 or 1000 times?  I am using Microsoft's compiler.
edit
here is the generated assembly for the real-world case I'm looking at.  line->addPoint() is the virtual method of concern. I have no assembly experience, so I'm going over it slowly...
; 369  :        for (int i = 0; i < numPts; ++i)
    test    ebx, ebx
    je  SHORT $LN1@RDS_SCANNE
    lea edi, DWORD PTR [ecx+32]
    npad    2
$LL3@RDS_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 $LL3@RDS_SCANNE
$LN314@RDS_SCANNE:
; 365  :        }
                In general, no, it is not possible. The function could destroy *this and placement-new some other object derived from the same base in that space.
Edit: even easier, the function could just change p. The compiler cannot possibly know who has the address of p, unless it is local to the optimization unit in question.
Impossible in general, but there are special cases that can be optimized, especially with inter-procedural analysis. VS2012 with full optimizations and whole-program optimization compiles this program:
#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);
}
to:
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)  
so it's effectively optimized the loop to:
for(int i = 0; i < 100; ++i)
  cout << "B::foo()\n";
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With