NOTE: Study this page carefully! A very large number of catastrophic errors made by Java programmers when they move to C++ are caused by not understanding the concepts described here!


Unlike Java, instances of classes ("objects") can be allocated on the stack in C++. That is, you do not need to use new to allocate an instance of an object. Version 2 of our class Complex at the bottom of the Classes page created c1 and c2 on the stack. (They were allocated on the heap – like Java – in Version 1.)

Among other things, the ability to create stack-allocated objects in C++ means that the following code – which is syntactically valid in both C++ and Java – causes quite different actions to be taken depending on whether it is compiled and executed as Java or C++ code.

          void reportGrievanceAgainst(Employee b) // Line 1
          {
              Employee x;                         // Line 2
              x = b;                              // Line 3
              b.logTheGrievance();                // Line 4
          }

Let's assume that Employee has been defined as a class. We will study this simple method line by line.

 
Behavior when compiled and executed as Java code
Behavior when compiled and executed as C++ code
Line 1
The prototype declares that the formal parameter 'b' is a reference to the instance of Employee that was passed as the actual parameter in the calling environment. Thus if we modify 'b' in the body of reportGrievanceAgainst, we will be changing that actual parameter. The prototype declares that the formal parameter 'b' is a stack-allocated instance of Employee local to the reportGrievanceAgainst function. When the function is called, 'b' is initialized with a copy of the Employee object passed as the actual parameter in the calling environment. (That is, the Employee instance is "passed by value" as discussed on the Parameter passing page.) Therefore if we modify 'b' in the body of reportGrievanceAgainst, we will modify the copy, not the actual parameter in the calling environment.
Line 2
The "Employee x;" statement causes a reference variable to be allocated. No actual Employee instance is created, and x is not initialized to point to anything (not even null). The "Employee x;" statement causes a different instance of an Employee (named 'x') to be allocated on the runtime stack and its no-parameter constructor to be invoked. The resulting instance is thus local (not heap-allocated), and it will be deleted upon exit from reportGrievanceAgainst.
Line 3
The Java code generated for the statement "x=b;" would simply make 'x' and 'b' refer to the same Employee instance. Each is now a reference to the instance of Employee that was passed as the actual parameter in the calling environment. The C++ code generated for the statement "x=b;" causes a copy of the Employee data in 'b' to be placed in the storage space allocated for the (local) Employee instance named 'x'. Although the two now have the same data, they remain independent instances, and both are independent of the actual parameter in the calling environment.
Line 4
The method "logTheGrievance" presumably modifies the data stored in the Employee instance so that the grievance is actually stored. Since 'b' references the actual parameter in the calling environment, the grievance actually gets logged in the data associated with the actual parameter in the calling environment. The end result would have been identical if line 4 were replaced by: x.logTheGrievance(); Since we are dealing with three independent instances of Employee, the changes made to 'b' are only made to that one instance. Both the local 'x' and the actual parameter in the calling environment continue to hold (separate copies of) the original data as passed to reportGrievanceAgainst.

Clearly the employee in question is hoping that this code was written by a naive C++ programmer!

The following table shows how another method could call reportGrievanceAgainst. The code in both columns of the table below is syntactically valid when interpreted as Java. By contrast, only the code in the C++ column would compile without errors by a C++ compiler. (Why? There are two reasons.)

Note also: Even though the code in the C++ column is syntactically valid when interpreted as Java, most Java compilers would detect that an uninitialized variable is being passed to reportGrievanceAgainst and would generate a compilation error.

Java
C++
void processTransactions( )
{
   Employee fred = new Employee( );
   reportGrievanceAgainst(fred);
}
void processTransactions( )
{
   Employee fred;
   reportGrievanceAgainst(fred);
}