Reputation: 3972
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?
Upvotes: 11
Views: 5037
Reputation: 1246
If use memcpy, there may some undefined behavior occur.
It's an implementation detail how the given class will be copied. Both memcpy() function and copy constructor will be converted into some machine code. However your objects in memory should not overlap because default assignment does not guarantee you'll have a proper result in case they overlap.
So, what's the default assign operation behavior in C++ object?
As in other responses, the behaviour is such that it will call assignments on all class/struct members recursively. However technically, as in your case, it may just copy whole block of memory, especially if your structure is POD (plain old data).
Upvotes: -1
Reputation: 234354
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.
Upvotes: 14
Reputation: 129314
Some limited experimentation tells me that g++ completely removes any attempt to copy a = a;
[assuming it is obvious - I'm sure with sufficient messing about with pointers, it will eventually be possible to copy the same object over itself, and get undefined behaviour].
Upvotes: 0
Reputation: 21763
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.
Upvotes: 5