33
votes

This is something I have wondered for a long time. Take the following example:

struct matrix
{
    float data[16];
};

I know what the default constructor and destructor do in this specific example (nothing), but what about the copy constructor and the copy assignment operator?

struct matrix
{
    float data[16];

    // automatically generated copy constructor
    matrix(const matrix& that) : // What happens here?
    {
        // (or here?)
    }

    // automatically generated copy assignment operator
    matrix& operator=(const matrix& that)
    {
        // What happens here?

        return *this;
    }
};

Does it involve std::copy or std::uninitialized_copy or memcpy or memmove or what?

2
This is not really C, but (mostly) C++.Dervin Thunk
@DervinThunk I changed the title of the question from C to C++jfritz42

2 Answers

45
votes

This is what the standard says in 12.8 (Copying class objects). Copy construction:

Each subobject is copied in the manner appropriate to its type:

  • if the subobject is of class type, the copy constructor for the class is used;
  • if the subobject is an array, each element is copied, in the manner appropriate to the element type;
  • if the subobject is of scalar type, the built-in assignment operator is used.

Copy assignment:

Each subobject is assigned in the manner appropriate to its type:

  • if the subobject is of class type, the copy assignment operator for the class is used (as if by explicit qualification; that is, ignoring any possible virtual overriding functions in more derived classes);
  • if the subobject is an array, each element is assigned, in the manner appropriate to the element type;
  • if the subobject is of scalar type, the built-in assignment operator is used.
1
votes

Both copies elements in the array (instead of doing nothing or copying pointer).

struct X
{
    char data_[100];
};


int main () 
{
    X orig, copy_assign;
    orig.data_[10] = 'a';
    copy_assign = orig;
    X copy_constructor(orig);
    printf("orginal10:%c, copy_assign10:%c, copy_constructor10:%c\n",orig.data_[10],copy_assign.data_[10],copy_constructor.data_[10]);
    copy_assign.data_[10] = 'b';
    printf("original10:%c, copy_assign10:%c, copy_constructor10:%c\n",orig.data_[10],copy_assign.data_[10],copy_constructor.data_[10]);
    copy_constructor.data_[10] = 'c';
    printf("original10:%c, copy_assign10:%c, copy_constructor10:%c\n",orig.data_[10],copy_assign.data_[10],copy_constructor.data_[10]);
    return 0;
}

running results:

orginal10:a, copy_assign10:a, copy_constructor10:a
original10:a, copy_assign10:b, copy_constructor10:a
original10:a, copy_assign10:b, copy_constructor10:c
  • From the first line of the result, we can see that at least something was copied (it is either the elements in the array, or the array pointer was copied).
  • From the next two lines, we can see that changing copy assigned objects and copy constructed objects' array did not change the original array. Therefore we conclude that elements were copied instead of array pointer.

Hope this example is clear.