Borland Online And The Cobb Group Present:


October, 1994 - Vol. 1 No. 10

Initialization versus assignment

In the accompanying article, C++ Programming Basics - Creating a smart pointer template class we describe a problem you could face if you created a smart pointer object from another smart pointer object of the same type. Both smart pointers will address the same block of memory and then try to delete that block of memory when they leave scope.

As you probably know, calling delete on the same pointer twice may yield unpredictable results­­in some cases the program may crash. Therefore, you may want to make it illegal for you or another programmer to copy one smart pointer's data to another.

Two ways to copy objects

In general, there are two situations you'll want to guard against: initializing a new smart pointer with an existing one and assigning one smart pointer to another. The difference between these two situations is important, but not always obvious.

For example, if you write these statements in your code

employee bob;
employee fred = bob;

the compiler will call the employee class's copy constructor to initialize the employee object fred. This is functionally equivalent to writing

employee fred(bob);

which calls the employee class's copy constructor explicitly.

On the other hand, if you write the statements

employee bob;
employee fred;
employee fred = bob;

the compiler will first use the default constructor to create the employee object fred and then call the employee class's assignment operator to initialize the object fred with the data from the object bob.

As we mentioned in the accompanying article, the compiler will provide default versions of these functions for your class if you don't declare them. The default version of the copy constructor the compiler creates is equivalent to

employee::employee(const employee& e)
{
  memcpy(name, e.name, 20);
  hourlyRate = hourlyRate;
}

The body of the assignment operator is similar.

For each data member of a class or struct, the compiler will perform a member-by-member copy to set the values in the target object. If a given member is a user-defined type, the compiler will call the copy constructor for that type. If, instead, the data member is a simple type (int, float, char, and so on), the compiler will perform a bitwise copy of that member.

Temporaries may require a copy constructor

Even if you don't assign or initialize objects with statements similar to those we've shown above, your program may still try to call the class's copy constructor. When the compiler needs to generate a temporary object from a current object, it will call the copy constructor of the object's class.

Typically, the compiler will create temporary objects whenever you pass or return an object by value. For example, if you write a function

printEmployeePayRate(employee emp)
{ cout << e.hourlyRate << endl; }

the compiler will create a temporary value for the parameter emp and then call the copy constructor for the employee class to initialize it.

Two solutions

There are two ways you can avoid problems with copying objects that shouldn't share data. First, you can implement deep copying. That is, you can write your own versions of the copy constructor and assignment operator functions to copy via a pointer the data that would have been shared.

Second, if copying the shared data isn't appropriate for your application, you can declare both functions but not provide a function body. If you do this, you'll prevent the compiler from creating the default versions of these functions, and the linker will display an error if any module in the application tries to call either of them.

Return to the Borland C++ Developer's Journal index

Subscribe to the Borland C++ Developer's Journal


Copyright (c) 1996 The Cobb Group, a division of Ziff-Davis Publishing Company. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of Ziff-Davis Publishing Company is prohibited. The Cobb Group and The Cobb Group logo are trademarks of Ziff-Davis Publishing Company.