Passing and Returning Objects

There are two other situations besides ordinary declarations in which the copy constructor may be called:

When a function takes an object as a parameter.

When a function returns an object.

The following example shows a function that takes an object as a parameter:

// Function that takes a String parameter

void consume( String parm )

{

// Use the parm object

}

void main()

{

String myString( "here's my string" );

consume( myString );

}

The function consume takes a String object passed by value. That means that the function gets its own private copy of the object.

The function's parameter is initialized with the object that is passed as an argument. The compiler implicitly calls the copy constructor to perform this initialization. It does the equivalent of the following:

// Hypothetical initialization of parameter

String parm( myString ); // Call copy constructor

Consider what happens if you don't define a copy constructor to handle initialization. As a result of the compiler's default initialization, the function's copy of the object has the same character buffer as the caller's copy; any operations on parm's buffer also modify myString's buffer. More importantly, the parameter has local scope, so the destructor is called to destroy it when the function finishes executing. That means that myString has a pointer to deleted memory, which makes it unsafe to use after the function is done.

The following example shows a function that returns an object:

// Function that returns a String

String emit()

{

String retValue( "here's a return value" );

return retValue;

}

void main()

{

String yourString;

yourString = emit();

}

The function emit returns a String object. The compiler calls the copy constructor to initialize a hidden temporary object in the caller's scope, using the object specified in the function's return statement.This hidden temporary object is then used as the right-hand side of the assignment statement. That is, the compiler performs the equivalent of the following:

// Hypothetical initialization of return value

String temp( retValue ); // Call copy constructor

yourString = temp; // Assignment of temp object

Once again, a copy constructor is needed. Otherwise, the temporary object shares the same character buffer as retValue, which is deleted when the function finishes executing, and the subsequent assignment to yourString is not guaranteed to work.

As a rule, you should always define both a copy constructor and an assignment operator whenever you write a class that contains pointer members and allocates memory from the free store.