eg, it puzzles me:
struct A {
// some fileds...
char buf[SIZE];
};
A a;
a = a;
Through A's field buf
, it looks like probably that the default assign operation will call something like memcpy
to assign an object X to Y, so what if assign an object to itself and there are no explicit assign operation defined, like a = a;
above.
memcpy manual page:
DESCRIPTION
The memcpy() function copies n bytes from memory area src to memory area dest. The memory areas must not overlap. Use memmove(3) if the memory areas do overlap.
If use memcpy
, there may some undefined behavior occur.
So, what's the default assign operation behavior in C++ object?
The assignment operator is not defined in terms of memcpy
(§12.8/28).
The implicitly-defined copy/move assignment operator for a non-union class X performs memberwise copy/move assignment of its subobjects. The direct base classes of X are assigned first, in the order of their declaration in the base-specifier-list, and then the immediate non-static data members of X are assigned, in the order in which they were declared in the class definition. Let x be either the parameter of the function or, for the move operator, an xvalue referring to the parameter. Each subobject is assigned in the manner appropriate to its type:
[...]
— if the subobject is an array, each element is assigned, in the manner appropriate to the element type;
[...]
As you see, each char
element will be assigned individually. That is always safe.
However, under the as-if rule, a compiler may replace this with a memmove
because it has identical behaviour for a char
array. It could also replace it with a memcpy
if it can guarantee that memcpy
will result in this same behaviour, even if theoretically such a thing is undefined. Compilers can rely on theoretically undefined behaviour; one of the reasons undefined behaviour exists is so that compilers can define it to whatever is more appropriate for their operation.
Actually, in this case a compiler could take the as-if rule even further and not do anything with the array at all, since that also results in the same behaviour.
Default assign (and copy) behaviour does not memcpy the whole class, which would break things. Each member is copied using their copy constructor or assignment operator (depending on operation). This is applied recursively for members and their members. When a basic data type is reached, it simply performs a straight copy of data, similar to memcpy. So an array of basic data types may be copied similar to memcpy, but the whole class is not. If you add std::string to your class its = operator would be called, alongside copy of array. If you used array of std::string, each string in your array will have their operator called. They won't memcpy.
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