Chapter 8: Object Reference and Memory Allocation


If we had to choose one word on which we could bestow the honor of being the source of the greatest confusion between C++ and Java, that word would be "reference". An object reference in C++ does not at all mean the same thing as an object reference in Java. In C++, the following phrase makes sense: "A variable serves as a reference for a previously created object." On the other hand, the following phrase is more appropriate for Java: "A variable holds a reference for a class-type object." On the face of it, the two phrases sound about the same; yet they have very different meanings. When a variable in Java holds a reference to a newly created object, it's like a pointer in C++ holding the memory address of an object. And when a variable in C++ serves as a reference for a previously created object, the variable becomes an alias for that object. The goal of this chapter is to clarify these usages of the word "reference" in C++ and Java. This chapter will also address the issues of memory allocation and deallocation, and the definition of structures in C++.

8.1 OBJECT REFERENCE IN C++

An object reference in C++ is merely an alternative name for an object or a variable. In C++, the notation

       T& 

means a reference for an object of type T. For example, we could say

      int i = 2;      int& r = i; 

With the second declaration, the variable r is a reference for the variable i; r is simply another name for the variable i. So if we say

      r = 3; 

we are also causing the value of i to become 3. You might think of r as serving as an alias for i. If you apply the address operator ‘&’ to r, you will get the address of i. That is,

      int* q = &r; 

will cause q to point to i. Now if we declare

      int* p = &i; 

the pointers p and q would both point to exactly the same location in the memory. And if we incremented r by

       r++; 

we would actually be incrementing i and achieving i++. Don't forget that, on the basis of the above discussion, if we want to obtain a pointer to an object that is referenced by the identifier r, all we have to do is to find[1]

      &r; 

The following declaration is an error:

      int& r = 100; // WRONG 

That's because the initializer for a T& type must be an object of type T whose address can be ascertained. The constant 100 has no address associated with it. This constraint does not apply to a reference of const T& type. For example, it would be legal to say

      const int& r = 100; 

You cannot change the object of a reference. Here is an example:

      int i = 3;      int j = 100;      int& r = i;      r++;                  // i is now 4      r = j;                // i is now 100      r++;                  // i is now 101

With these declarations, r remains a reference to i no matter what happens subsequently.

You can even have a reference for a pointer type, as the following example illustrates:

      int i = 3;      int* p = &i;      int*& q = p;     // q serves as a reference for pointer p      cout << *q;      // will output 3      *q = 100;        // i is now 100      cout << *p;      // will output 100      cout << i;       // will output 100 

While our discussion above used examples involving only the primitive types in C++, exactly the same considerations apply to class-type objects, as we demonstrate in the following C++ program:

 
//ReferenceClassType.cc #include <iostream> #include <string> using namespace std; class User { public: string name; int age; User( string nam, int a ) { name = nam; age = a; } }; int main() { User u1( "Melinda", 87 ); //(A) User* u2 = new User( "Belinda", 129 ); //(B) User& u3 = u1; //(C) const User& u4 = User( "Tralinda",87 ); //(D) cout << u1.name << endl; // Melinda //(E) cout << u2->name << endl; // Belinda cout << u3.name << endl; // Melinda //(F) cout << u4.name << endl; // Tralinda User*; p = &u1; //(G) User*; q = &u3; //(H) cout << p->name << endl; // Melinda //(I) cout << q->name << endl; // Melinda //(J) return 0; }

Lines (A) through (D) of the program define four different kinds of variables. The variable u1 gives us direct access to a new User whose name is Melinda. The variable u2 is a pointer to a new User of name Belinda. The variable u3 is a reference for the object u1. And, finally, u4 is a const reference to a User object with name Tralinda.[2] In accordance with our earlier discussion, u3 serves as an alias for u1. Therefore, the output statements in lines (E) and (F) yield the same answer—Melinda. Also, the two declarations for the pointers p and q in lines (G) and (H), respectively, yield the memory address of the same object—the User with name Melinda—as borne out by the output in lines (I) and (J).

[1]Some beginning programmers might say that maybe an analogy could be drawn between a C++ object reference and a pointer. They might say r serves as some sort of a pointer to i. This analogy breaks down immediately when you realize that the ostensibly dereferencing operation *r is illegal because r is NOT a pointer.

[2]Note that for u4 you would get either a compiler warning or a compiler error if you declared

      User& u4 = User( "Tralinda", 187 ); 

without the const. It's for the same reason that the declaration "int& r = 100;" is an error, as pointed out previously. The initializer for a variable that's to serve as a reference must be an object whose memory address can be ascertained. That the object on the right above is not something whose address can be ascertained is made clear by the fact that the following statement is unacceptable to the compiler

      User* p = &User( "Tralinda", 187 );           // WRONG 




Programming With Objects[c] A Comparative Presentation of Object-Oriented Programming With C++ and Java
Programming with Objects: A Comparative Presentation of Object Oriented Programming with C++ and Java
ISBN: 0471268526
EAN: 2147483647
Year: 2005
Pages: 273
Authors: Avinash Kak

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net