There is nothing undefined here. If there are virtual functions, then the vtable will get copied, too. Not a great idea, but if the types are the same it is will work.
The problem is that you need to know the details of everything in the class. Even if there are no pointers, maybe there is a unique id assigned by the constructor, or any of a thousand other things that can't just be copied. Using memcpy is like telling the compiler that you know exactly what you are doing. Make sure that's the case.
Edit: There is a big spread of possible interprtations between "not defined in the C++ standard" and "might format my hard drive with the compiler I'm using." Some clarification follows.
Classic Undefined Behavior
Here is an example of behavior that everyone would probably agree is undefined:
void do_something_undefined()
{
int i;
printf("%d",i);
}
Not Defined By C++ Standard
You can use a different, more strict definition of undefined. Take this code fragment:
struct MyStruct
{
int a;
int b;
MyStruct() : a(1),b(2)
{
}
~MyStruct()
{
std::cout << "Test: Deleting MyStruct" << std::endl;
}
};
void not_defined_by_standard()
{
MyStruct x,y;
x.a = 5;
memcpy(&y, &x, sizeof(MyStruct)); // or std::memcpy
}
Taking the previous posters at their word on the standard references, this use of memcpy is not defined by the C++ standard. Perhaps it is theoretically possible that a C++ standard could add a unique ID to each non-trivially destructed class, causing the destructors of x and y to fail. Even if this is permitted by the standard, you can certainly know, for your particular compiler, if it does or does not do this.
I would make semantic difference here and call this "not defined" instead of "undefined." one problem is the lawyer-like definition of terms: "Undefined Behavior" in the C++ standard means "not defined in the standard", not "gives an undefined result when using a particular compiler." While the standard may not define it, you can absolutely know if it is undefined with your particular compiler. (Note that cppreference of std::memcpy says "If the objects are not TriviallyCopyable, the behavior of memcpy is not specified and may be undefined". This says memcpy is is unspecified behavior not undefined behavior, which is kind-of my whole point.)
So, again, you need to know exactly what you are doing. If you're writing portable code that needs to survive for years, don't do it.
Why does the C++ standard not like this code?
Simple: The memcpy call above effectively destructs and re-constructs y. It does this without calling the destructor. The C++ standard rightly does not like this at all.