Suppose I have any kind of class or structure. No virtual functions or anything, just some custom constructors, as well as a few pointers that would require cleanup in the destructor.
Would there be any adverse affects to using memcpy or memmove on this structure? Will deleting a moved structure cause problems? The question assumes that the memory alignment is also correct, and we are copying to safe memory.
In the general case, yes, there will be problems. Both memcpy
and memmove
are bitwise operations with no further semantics. That might not be sufficient to move the object*, and it is clearly not enough to copy.
In the case of the copy it will break as multiple objects will be referring to the same dynamically allocated memory, and more than one destructor will try to release it. Note that solutions like shared_ptr
will not help here, as sharing ownership is part of the further semantics that memcpy
/memmove
don't offer.
For moving, and depending on the type you might get away with it in some cases. But it won't work if the objects hold pointers/references to the elements being moved (including self-references) as the pointers will be bitwise copied (again, no further semantics of copying/moving) and will refer to the old locations.
The general answer is still the same: don't.
* Don't take move here in the exact C++11 sense. I have seen an implementation of the standard library containers that used special tags to enable moving objects while growing buffers through the use of memcpy
, but it required explicit annotations in the stored types that marked the objects as safely movable through memcpy
, after the objects were placed in the new buffer the old buffer was discarded without calling any destructors (C++11 move requires leaving the object in a destructible state, which cannot be achieved through this hack)
Generally using memcpy on a class based object is not a good idea. The most likely problem would be copying a pointer and then deleting it. You should use a copy constructor or assignment operator instead.
No, don't do this.
If you memcpy
a structure whose destructor deletes a pointer within itself, you'l wind up doing a double delete when the second instance of the structure is destroyed in whatever manner.
The C++ idiom is copy constructor for classes and std::copy
or any of its friends for copying ranges/sequences/containers.
If you are using C++11, you can use std::is_trivially_copyable to determine if an object can be copied or moved using memcpy
or memmove
. From the documentation:
Objects of trivially-copyable types are the only C++ objects that may be safely copied with std::memcpy or serialized to/from binary files with std::ofstream::write()/std::ifstream::read(). In general, a trivially copyable type is any type for which the underlying bytes can be copied to an array of char or unsigned char and into a new object of the same type, and the resulting object would have the same value as the original.
Many classes don't fit this description, and you must beware that classes can change. I would suggest that if you are going to use memcpy
/memmove
on C++ objects, that you somehow protect unwanted usage. For example, if you're implementing a container class, it's easy for the type that the container holds to be modified, such that it is no longer trivially copyable (eg. somebody adds a virtual function). You could do this with a static_assert
:
template<typename T>
class MemcopyableArray
{
static_assert(std::is_trivially_copyable<T>::value, "MemcopyableArray used with object type that is not trivially copyable.");
// ...
};
Aside from safety, which is the most important issue as the other answers have already pointed out, there may also be an issue of performance, especially for small objects.
Even for simple POD types, you may discover that doing proper initialization in the initializer list of your copy constructor (or assignments in the assignment operator depending on your usage) is actually faster than even an intrinsic version of memcpy
. This may very well be due to memcpy's entry code which may check for word alignment, overlaps, buffer/memory access rights, etc.... In Visual C++ 10.0 and higher, to give you a specific example, you would be surprised by how much preamble code that tests various things executes before memcpy even begins its logical function.
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