Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the c++'s default assign operation behavior?

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?

like image 983
大宝剑 Avatar asked Aug 06 '13 12:08

大宝剑


2 Answers

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.

like image 197
R. Martinho Fernandes Avatar answered Oct 03 '22 17:10

R. Martinho Fernandes


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.

like image 37
Neil Kirk Avatar answered Oct 03 '22 19:10

Neil Kirk