Overloaded Assignment Operator Copy Constructor Java

The latest version of this topic can be found at Copy Constructors and Copy Assignment Operators (C++).

NOTE]

Starting in C++11, two kinds of assignment are supported in the language: copy assignment and move assignment. In this article "assignment" means copy assignment unless explicitly stated otherwise. For information about move assignment, see Move Constructors and Move Assignment Operators (C++).

Both the assignment operation and the initialization operation cause objects to be copied.

  • Assignment: When one object's value is assigned to another object, the first object is copied to the second object. Therefore,

    causes the value of to be copied to .

  • Initialization: Initialization occurs when a new object is declared, when arguments are passed to functions by value, or when values are returned from functions by value.

You can define the semantics of "copy" for objects of class type. For example, consider this code:

The preceding code could mean "copy the contents of FILE1.DAT to FILE2.DAT" or it could mean "ignore FILE2.DAT and make a second handle to FILE1.DAT." You must attach appropriate copying semantics to each class, as follows.

  • By using the assignment operator together with a reference to the class type as the return type and the parameter that is passed by reference—for example .

  • By using the copy constructor. For more information about the copy constructor, see Rules for Declaring Constructors.

If you do not declare a copy constructor, the compiler generates a member-wise copy constructor for you. If you do not declare a copy assignment operator, the compiler generates a member-wise copy assignment operator for you. Declaring a copy constructor does not suppress the compiler-generated copy assignment operator, nor vice versa. If you implement either one, we recommend that you also implement the other one so that the meaning of the code is clear.

Member-wise assignment is covered in more detail in (NOTINBUILD) Memberwise Assignment and Initialization.

The copy constructor takes an argument of type class-name&, where class-name is the name of the class for which the constructor is defined. For example:

Make the type of the copy constructor's argument const class-name& whenever possible. This prevents the copy constructor from accidentally changing the object from which it is copying. It also enables copying from const objects.

Compiler-generated copy constructors, like user-defined copy constructors, have a single argument of type "reference to class-name." An exception is when all base classes and member classes have copy constructors declared as taking a single argument of type constclass-name&. In such a case, the compiler-generated copy constructor's argument is also const.

When the argument type to the copy constructor is not const, initialization by copying a const object generates an error. The reverse is not true: If the argument is const, you can initialize by copying an object that is not const.

Compiler-generated assignment operators follow the same pattern with regard to const. They take a single argument of type class-name& unless the assignment operators in all base and member classes take arguments of type constclass-name&. In this case, the class's generated assignment operator takes a const argument.

When virtual base classes are initialized by copy constructors, compiler-generated or user-defined, they are initialized only once: at the point when they are constructed.

The implications are similar to those of the copy constructor. When the argument type is not const, assignment from a const object generates an error. The reverse is not true: If a const value is assigned to a value that is not const, the assignment succeeds.

For more information about overloaded assignment operators, see Assignment.

Special Member Functions

TextFile a, b; a.Open( "FILE1.DAT" ); b.Open( "FILE2.DAT" ); b = a;
// spec1_copying_class_objects.cpp class Window { public: Window( const Window& ); // Declare copy constructor. // ... }; int main() { }

First some basics about copy construction and copy assignment in C++ and Java

C++ and Java are two very different beasts due to object semantics in C++ and Reference semantics in Java. What I mean by this is:

In C++ this line denotes a new object that gets initialized with . In Java, this line creates not a new object but a new reference to an object, and that reference refers to what ever the expression gives. Java references can be null, meaning "no object". C++ objects are, so there is no "no object"-object ;-) Java references are very much like C++ pointers. The only thing that can make the distinction difficult is that while C++ has pointers and objects and dereferences pointers with , in Java everything is a reference (except int and a few other basic types), and accessing objects through references uses , wich easily can be confused with access to "direct" objects in C++. "Everything is a reference" means, that any object (except int & Co.) is conceptually created on the heap.

Having said that, let's have a look at assignments and copies in both languages.

Copy construction means the same in both languages, you essentially create a new object that is a copy of another. Copy constructor definition is similar:

The difference is only that C++ explicitly has to declare the parameter as a reference, while in Java everything is a reference anyways. Writing the first line in C++ would define a constructor that takes it's argument by copy, i.e. the compiler would have to create a copy already, using the copy constructor, for which it has to create a copy,... - not a good idea.

Using copy construction in the two languages will look like this:

When you look at the first and third line, they look essentially the same. This is because they are essentially the same, since Java references are essentially like pointers in C++. Both expressions create a new object that can outlive the function scope it is created in. The second line creates a plain C++ object on the stack, wich does not exist in Java. In C++, copies are also created implicitly by the compiler eg. when an object is passed to a function that accepts its parameter by value instead of by reference.

Defining copy assignment: In C++, you can define wich (normally) assigns the values of an object to an already existing object, discarding the old values of the object you assign to. If you don't define it yourself, the compiler will do it's best to generate one for you, doing a plain elementwise copy of the objects' elements. In Java, you cannot overload operators, so you will have to define a method, called e.g. :

Note thet here again we explicitly declare the parameter as reference in C++ but not in Java.

Using copy assignment:

Here the first two lines look exactly the same but could not be more different. Remember that in C++, and deonte the objects themselves, while in Java they are only references. So in C++ this is copy assignment on objects, meaning you finish with two objects that have the same content. After changing you will have with the value that had before the assignment, while has changed.
In Java (line 2) that assignment is an assignment of references, meaning after that the two references and refer to the very same object, while the object previously referred ba is not referred to any more and so it will be garbage collected. Calling will change the single object both references point to and accessing it through the reference will reveal these changes.
Again it's (nearly) the same with C++ pointers. You see you cannot distinguish the syntax of object and pointer assignment, it's all determined by the types that get assigned. The difference with C++ is that it has no garbace collector and you end up with a memory leak because the object pointed to can not be deleted any more.

About your question:

Consider a C++ class:

Suppose each X object allocates it's own dynamic array of ints, the pointer to it gets stored in . Since C++ has no garbage collection, the X objects have to care themselves for their allocated memory, i.e. they have to destroy it manually:

A copy constructor will copy the dynamic array of the original, so the two do not conflict while using the same array. This is called deep copy and is used equally in Java and C++:

Now to the qoute in your question: Consider two objects x1 and x2 and the assignment . If you leave everythign to the compiler, it will generate an assignment operator like this:

In the first line gets the pointer value of . Like I explained in the section about copy assignment, this will lead to both pointers pointing to the same array, and the array previously owned by will be lost in space, meaning you have a leak and odd behavior when both objects work on their shared array.
The correct implementation would be:

Here you see what the quote says: First, the object is "cleaed up", i.e. the memory is freed, essentially doing what the destructor does ("instance has to be destroyed"). Then, the deep copy is performed, doing what the copy constructor does ("...and re-initialized").

This is called the "Rule of Three": If you have to write your own copy constructor (because the generated one does not what you want it to do), you will mostly have to write your own destructor and assignment operator as well. Since C++11 it has become the "Rule of Five", because you have move assignment and move construction that have to be considered as well.

0 comments

Leave a Reply

Your email address will not be published. Required fields are marked *