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