vtable always needed

S

stef

Hello,

Could you tell me why did a C++ compiler really need to use a v-table
in this case :


#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }
};

struct B: A {
virtual void f() { cout << "Class B" << endl; }
};



int main()
{
B x;
A *ptr;

ptr = &x;

// could be "compute" statically ?
ptr->f();

return 1;
}


thanks...
 
M

mlimber

Hello,

Could you tell me why did a C++ compiler really need to use a v-table
in this case :

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }

};

struct B: A {
virtual void f() { cout << "Class B" << endl; }

};

int main()
{
B x;
A *ptr;

ptr = &x;

// could be "compute" statically ?
ptr->f();

return 1;

}

thanks...

I could conceive of an optimizer getting rid of such a virtual
function call, but since obvious optimizations like this are rare in
real code, I wouldn't be surprised if the optimizer didn't bother.

Cheers! --M
 
E

E. Robert Tisdale

stef said:
Could you tell me
why did a C++ compiler really need to use a v-table in this case:
> cat fred.cc
#include <iostream>
using namespace std;

struct A {
virtual void f(void) {
std::cout << "Class A" << std::endl; }
};

struct B: A {
virtual void f(void) {
std::cout << "Class B" << std::endl; }
};

void fred(void) {
B x;
A *ptr;

ptr = &x;

// could be "compute" statically?
ptr->f();

return;
}
> g++ -Wall -ansi -O2 -S fred.cc
fred.cc:4: warning: ‘struct A’ has virtual functions
but non-virtual destructor
fred.cc:9: warning: ‘struct B’ has virtual functions
but non-virtual destructor
> cat fred.s
.
.
.
_Z4fredv:
.LFB1435:
pushl %ebp
.LCFI0:
movl %esp, %ebp
.LCFI1:
subl $24, %esp
.LCFI2:
leal -4(%ebp), %eax
movl $_ZTV1B+8, -4(%ebp)
movl %eax, (%esp)
call *_ZTV1B+8
leave
ret
.
.
.
_ZTV1B:
.long 0
.long _ZTI1B
.long _ZN1B1fEv
.weak _ZTI1B
.section .rodata._ZTI1B,"aG",@progbits,_ZTI1B,comdat
.align 4
.type _ZTI1B, @object
.size _ZTI1B, 12
.
.
.
> c++filt _ZTV1B vtable for B
> c++filt _ZN1B1fEv B::f()
> g++ --version
g++ (GCC) 4.1.1 20070105 (Red Hat 4.1.1-51)

My optimizing C++ compiler actually calls B::f() directly.
 
S

Salt_Peter

Hello,

Could you tell me why did a C++ compiler really need to use a v-table
in this case :

#include <iostream>
using namespace std;

struct A {
virtual void f() { cout << "Class A" << endl; }

};

struct B: A {
virtual void f() { cout << "Class B" << endl; }

};

int main()
{
B x;
A *ptr;

ptr = &x;

// could be "compute" statically ?
ptr->f();

return 1;

}

thanks...

What if you added:

struct C: B {
};

int main()
{
C x;
A *ptr;

ptr = &x;

ptr->f(); // what should the compiler do here?
}
 
M

Markus Moll

Hi

Salt_Peter said:
What if you added:

struct C: B {
};

int main()
{
C x;
A *ptr;

ptr = &x;

ptr->f(); // what should the compiler do here?
}

Of course it should still call B::f(), and that could be easily
determined at compile-time, without the need for any runtime dispatch.

Markus
 
M

Markus Moll

Hi

E. Robert Tisdale said:
.LCFI2:
leal -4(%ebp), %eax
movl $_ZTV1B+8, -4(%ebp)
movl %eax, (%esp)
call *_ZTV1B+8
leave
ret
.
.
.
_ZTV1B:
.long 0
.long _ZTI1B
.long _ZN1B1fEv
.weak _ZTI1B
.section .rodata._ZTI1B,"aG",@progbits,_ZTI1B,comdat
.align 4
.type _ZTI1B, @object
.size _ZTI1B, 12 [...]
My optimizing C++ compiler actually calls B::f() directly.

Well, I would only call "call _ZN1B1fEv" a direct call to B::f().
But that's strange. The compiler is smart enough to know that it's
dealing with a "B" and eliminates the indirection through the pointer to
the virtual table, but still it cannot infer that it should therefore
simply call B::f()?

Could it be that this is because gcc does not want to break code where
people intentionally mess around with virtual tables while the program
is running?

Markus
 
E

E. Robert Tisdale

Markus said:
Hi

E. Robert Tisdale said:
.LCFI2:
leal -4(%ebp), %eax
movl $_ZTV1B+8, -4(%ebp)
movl %eax, (%esp)
call *_ZTV1B+8
leave
ret
.
.
.
_ZTV1B:
.long 0
.long _ZTI1B
.long _ZN1B1fEv
.weak _ZTI1B
.section .rodata._ZTI1B,"aG",@progbits,_ZTI1B,comdat
.align 4
.type _ZTI1B, @object
.size _ZTI1B, 12 [...]
My optimizing C++ compiler actually calls B::f() directly.

Well, I would only call "call _ZN1B1fEv" a direct call to B::f().
But that's strange. The compiler is smart enough to know that it's
dealing with a "B" and eliminates the indirection through the pointer to
the virtual table, but still it cannot infer that it should therefore
simply call B::f()?

Could it be that this is because gcc does not want to break code where
people intentionally mess around with virtual tables while the program
is running?

I don't know.
I'd guess that the optimizer is still "suboptimal".
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,534
Members
45,008
Latest member
Rahul737

Latest Threads

Top