#include <cstdio>
#include <cstring>
class A
{
public:
virtual void foo()
{
puts("A");
}
};
class B : public A
{
public:
void foo()
{
puts("B");
}
};
int main()
{
A a;
B b;
memcpy(&a, &b, sizeof (b));
(&a)->foo();
}
-
3You know you're blowing the stack to smithereens should `B` ever be bigger than `A`? – Xeo Jun 24 '11 at 13:28
-
2This is UB, but if you were trying to figure out if how hard you can blow your own foot, try with an extra level of indirection: pass the modified `A` object to a function like: `void call( A& x ) { x.foo(); }`, since it is UB you might get anything at all, even `B` being printed... or a crash now or in production code, or... I don't believe in demons but *nasal demons*, those are real! – David Rodríguez - dribeas Jun 24 '11 at 13:35
-
Undefined behavior explains everything. – Qian Jun 24 '11 at 13:51
-
This is almost more C than C++. Yes, there are classes, but cstdio and cstring? Why not use the C++ library? – kiswa Jun 24 '11 at 15:42
6 Answers
Doing raw memory manipulation (such as memcpy
) on non-POD types invokes undefined behaviour. You shouldn't do it!

- 267,707
- 33
- 569
- 680
-
(And, almost by extension, because there's _more to an object_ than the bytes that you can physically `memcpy`.) – Lightness Races in Orbit Jun 24 '11 at 13:28
-
1@Tomalak: So is `sizeof(b)` not guaranteed to encapsulate *everything* related to the storage of `b`? (Genuine question.) – Oliver Charlesworth Jun 24 '11 at 13:30
-
@Oli Charlesworth: it encapsulates everything not indirectly referenced. – Matthieu M. Jun 24 '11 at 13:43
-
@Oli: Good question. I'm wondering whether the bytes under storage are guaranteed to encapsulate all the semantic information of the object. Consider the fact of the object's type, for starters. – Lightness Races in Orbit Jun 24 '11 at 13:46
-
My saying: The size of a `struct` or `class` *may not* equal the sum of the size of the members. – Thomas Matthews Jun 24 '11 at 20:07
You are not supposed to mess with non-POD types like that. In particular, the C++ standard says that memcpy
ing non-PODs results in undefined behavior, which, in your case, shows as continuing to see a
as being of type A
.
In your particular case, the compiler "knows" that the both the "static type" and the "dynamic type" of a
is A
(since its type can't "legally" change - your trick is illegal), so no virtual dispatch is performed, but a.foo()
is called directly (and your trick of overwriting the vptr thus has no effect).

- 129,499
- 52
- 291
- 397

- 123,740
- 17
- 206
- 299
Because you're riding roughshod over any and all guarantees with your memcpy
, and are lucky to get any behaviour at all. Use the assignment operator as you're supposed to!

- 17,166
- 1
- 38
- 51
-
Actually, the assignment operator wouldn't help here. But at least the result would be well-defined. – Oliver Charlesworth Jun 24 '11 at 13:27
-
Because – why should it? The compiler sees that a
isn’t a pointer or reference and therefore cannot call anything but the original implementation of foo
. The compiler doesn’t bother to make the call virtual (because that is needlessly expensive).
As Oli said, your byte copy provokes undefined behaviour. Anything goes.

- 530,221
- 131
- 937
- 1,214
memcpy(&a, &b, sizeof (b));
(&a)->foo();
This is undefined behavior. This is guaranteed to work only for POD-types. So... UB is UB. No need to be surprised

- 1
- 1

- 130,161
- 59
- 324
- 434
A a;
B b;
memcpy(&a, &b, sizeof (b));
You will have an access violation in this code if A would have an members. Right way is next:
A a;
B b;
A *c = &a;
c->foo(); //A::foo()
c = &b;
c->foo(); //B::foo()

- 2,373
- 3
- 15
- 27