For a trivially copyable type T consider:
void f(T z)
{
T a;
T b;
std::memcpy(&b, &a, sizeof(T));
a = z;
b = z;
// ...
}
Is the behavior of this fragment defined in C++14 if
- T is char,
- T is int, or
- T is struct { int data; }; ?
Assume that f
gets passed an object that holds a valid value.
Do the answers change if the call to memcpy
is replaced by copy assignment b = a
?
Can the results be carried over to copy construction T(a)
and move construction/assignment?
Note: This question, in contrast to What are Aggregates and PODs and how/why are they special?, is particularly concerned with the corner case of copying indeterminate values.
There are a couple things at play here:
unsigned char
(and possiblychar
, if unsigned) is the exceptionThis means that
unsigned char
is fine, no matter whether usingmemcpy
ormemmove
or copy-assignment or copy-constructormemcpy
andmemmove
is presumably fine for all types, because the result is not "produced by an evaluation" (to meet this requirement, an implementation can useunsigned char
internally, or take advantage of implementation-specific guarantees made for other types)Of course, even the valid methods for copying an indeterminate value create another indeterminate value.
Paragraph numbers correspond to draft n4527
Yes, it's well defined for all those cases. The answers do not change if
memcpy
is replaced by copy assignment (copying for trivially copyable types is byte-wise copy. That's what makes it trivial), and for all trivially copyable types, move construction IS copy construction, so there's no difference there either.From [basic.types]:
and:
where:
Where, from [class]:
So,
char
,int
, andstruct { int data; };
are all trivially copyable types. The former two are cv-unqualified scalar types and the latter is a trivially copyable class type.