tags:

views:

131

answers:

2

Why does C++'s vector class call copy constructors? Why doesn't it just memcpy the underlying data? Wouldn't that be a lot faster, and remove half of the need for move semantics?

I can't imagine a use case where this would be worse, but then again, maybe it's just because I'm being quite unimaginative.

+11  A: 

Because the object needs to be notified that it is being moved. For example, there could be pointers to that given object that need to be fixed because the object is being copied. Or the reference count on a reference counted smart pointer might need to be updated. Or....

If you just memcpy'd the underlying memory, then you'd end up calling the destructor twice on the same object, which is also bad. What if the destructor controls something like an OS file handle?

EDIT: To sum up the above: The copy constructor and destructor can have side effects. Those side effects need to be preserved.

Billy ONeal
How does the destructor get called twice?
Clark Gaebel
Why does the reference count need updating? There are still the same number of references!
Clark Gaebel
You memcpy'd the object. Now there are two copies of it. The destructor needs to be called on both.
Billy ONeal
Oh, of course. Thank you. Didn't think about that!
Clark Gaebel
+3  A: 

You can safely memcpy POD and built-in types. Those are defined to have no semantics beyond being a bag of bits with respect to memory.

Types that have constructors and destructors, however, must be constructed and destructed in order to maintain invariants. While you may be able to create types that can be memcpy'd and have constructors, it is very difficult to express that in the type signature. So instead of possibly violating invariants associated with all types that have constructors and/or destructors, STL errs on the side of instead maintaining invariants by using the copy constructor when necessary.

This is why C++0x added move semantics via rvalue references. It means that STL containers can take advantage of types that provide a move constructor and give the compiler enough information to optimize out otherwise expensive construction.

MSN
Note that `std::copy<InputIter, OutputIter>` may in fact use `std::memcpy` when InputIter::value_type is the same as OutputIter::value_type and a POD.
MSalters