This question has been bothering me for some time. The possibilities I am considering are
Does a
Use std::copy
unless profiling shows you a needed benefit in doing otherwise. It honours the C++ object encapsulation, invoking copy constructors and assignment operators, and the implementation could include other inline optimisations. That's more maintainable if the types being copied are changed from something trivially copyable to something not.
As PeterCordes comments below, modern compilers such as GCC and clang analyse memcpy()
requests internally and typically avoid an out-of-line function call, and even before that some systems had memcpy()
macros that inlined copies below a certain size threshold.
FWIW / on the old Linux box I have handy (in 2010), GCC doesn't do any spectacular optimisations, but bits/type_traits.h
does allow the program to easily specify whether std::copy
should fall through to memcpy()
(see code below), so there's no reason to avoid using std::copy()
in favour of memcpy()
directly.
* Copyright (c) 1997
* Silicon Graphics Computer Systems, Inc.
*
* Permission to use, copy, modify, distribute and sell this software
* and its documentation for any purpose is hereby granted without fee,
* provided that the above copyright notice appear in all copies and
* that both that copyright notice and this permission notice appear
* in supporting documentation. Silicon Graphics makes no
* representations about the suitability of this software for any
* purpose. It is provided "as is" without express or implied warranty.
...
/*
This header file provides a framework for allowing compile time dispatch
based on type attributes. This is useful when writing template code.
For example, when making a copy of an array of an unknown type, it helps
to know if the type has a trivial copy constructor or not, to help decide
if a memcpy can be used.
The class template __type_traits provides a series of typedefs each of
which is either __true_type or __false_type. The argument to
__type_traits can be any type. The typedefs within this template will
attain their correct values by one of these means:
1. The general instantiation contain conservative values which work
for all types.
2. Specializations may be declared to make distinctions between types.
3. Some compilers (such as the Silicon Graphics N32 and N64 compilers)
will automatically provide the appropriate specializations for all
types.
EXAMPLE:
//Copy an array of elements which have non-trivial copy constructors
template void
copy(_Tp* __source,_Tp* __destination,int __n,__false_type);
//Copy an array of elements which have trivial copy constructors. Use memcpy.
template void
copy(_Tp* __source,_Tp* __destination,int __n,__true_type);
//Copy an array of any type by using the most efficient copy mechanism
template inline void copy(_Tp* __source,_Tp* __destination,int __n) {
copy(__source,__destination,__n,
typename __type_traits<_Tp>::has_trivial_copy_constructor());
}
*/