Assignment of objects in C++

user1493813 picture user1493813 · Nov 12, 2013 · Viewed 37.4k times · Source

To contextualize my question, I'm using a Matrix class with the following definitions:

Matrix(unsigned int, unsigned int); // matrix of the given dimension full of zeroes
Matrix(Matrix*); // creates a new matrix from another one
int &operator()(int, int);  // used to access the matrix
int **matrix; // the matrix

Now take these two code snippets:

First:

Matrix test(4,4);
Matrix ptr = test;
ptr(0,0) = 95;

Second:

Matrix test(4,4);
Matrix *ptr = &test;
(*ptr)(0,0) = 95;

Both codes have the same effect, the element in the (0,0) position receives 95 (The first snippet is very similar to Java, the reason which led me to ask this question). The question is, are both ways correctly making the assignment of the object?

Answer

Beta picture Beta · Nov 12, 2013

This is a little complicated.

Consider this simple class:

class Thing1
{
public:
  int n;
}

Now we try the first experiment:

Thing1 A;
A.n = 5;

Thing1 B = A;
B.n = 7;

cout << A.n << " " << B.n << endl;

The result is "5 7". A and B are two separate, independent objects. Changing one doesn't change the other.

Second experiment:

Thing1 *p = &A;
p->n = 9;

cout << A.n << " " << p->n << endl;

The result is "9 9"; p is a pointer to A, so A.n and p->n are the same thing.

Now things get complicated:

class Thing2
{
public:
  int *p;
};

...
Thing2 A;
A.p = new int(2);

Thing2 B = A;
*(B.p) = 4;

cout << *(A.p) << " " << *(B.p) << endl;

Now the result is "4 4". The assignment B = A copied the pointer, so although A and B are two different objects, their pointers point to the same int. This is a shallow copy. In general, if you want to make a deep copy (that is, each Thing points to an int of its own) you must either do it by hand or give the class an assignment operator which will handle it. Since your Matrix class doesn't have an explicit assignment operator, the compiler gives it the default-- which is a shallow copy. That's why, in your first snippet, both matrices appear to be changed.

EDIT: Thanks to @AlisherKassymov, for pointing out that declarations of the form Thing A=B; use the copy constructor, not the assignment operator. So for the solution to work in the above code, the copy constructor must make a deep copy. (Note that if the copy constructor does it, you almost certainly want the assignment operator to do it too (see the Rule of Three). Also note that if these functions get complicated, it makes sense to simply have the copy constructor invoke the assignment operator.)