Sunday, September 7, 2014

C++ Reference Vs Pointer

Reference Pointer
A reference is a variable that refers to something else and can be used as an alias for that something else. A reference is the object. A reference can be thought of as a constant pointer (not to be confused with a pointer to a constant value!) with automatic indirection, i.e. the compiler will apply the * operator for you. A pointer is a variable that stores a memory address, for the purpose of acting as an alias to what is stored at that address.
Const references can be bound to temporaries. This makes const& safer for use in argument lists and so forth. Pointers cannot (not without some indirection).
    const int &x = int(12);     // legal C++
    int *y = &int(12);          // illegal to dereference 
                                // a temporary.
    
A reference cannot be reassigned, and must be assigned at initialization. A reference can not be re-seated/reassigned after binding. A reference, always refers to the object with which it is initialized A pointer can be re-assigned any number of times.
    int x = 5;
    int y = 6;
    int *p;
    p = &x;     // p points to x
    p = &y;     // p now points to y
    *p = 10;    // p now is 10

    // Another special example

    string s1("Nancy");  
    string s2("Clancy");  
    string& rs = s1;    // rs refers to s1  
  
    string *ps = &s1;   // ps points to s1 
  
    rs = s2;    // rs still refers to s1,  
                // but s1's value is now "Clancy", 
                // as if s1 = s2  
  
    ps = &s2;   // ps now points to s2;  
                // s1 is unchanged   
    
References always refer to an object. Because a reference must refer to an object, C++ requires that references be initialized
    string& rs;         // error! References must  
                        // be initialized  
    string s("xyzzy");  
    string& rs = s;     // okay, rs refers to s  
    int &r = NULL;      //<--- compiling error 
    
Pointers can point to nowhere (NULL).
    string *ps;     // uninitialized pointer
                    // Its valid but risky  
    int *p = NULL;
    
The fact that there is no such thing as a null reference implies that it can be more efficient to use references than to use pointers. That's because there's no need to test the validity of a reference before using it
    void printDouble(const double& rd)  
    {  
        cout << rd; // no need to test rd; it  
    } 
    
Pointers, on the other hand, should generally be tested against null.
    void printDouble(const double *pd)  
    {  
        if (pd) // check for null pointer
        {               
            cout << *pd;  
        }  
    } 
    
You can't test if a reference is NULL.
    if(&ref == NULL)    // Not possible
    
You can test if a pointer is NULL.
    if(*ptr == NULL)    // Possible
    
References only offer one level of indirection. You can have pointers to pointers to pointers offering extra levels of indirection.
You can't take the address of a reference. You can take the address of a pointer.
There's no "reference arithmetics" (but you can take the address of an object pointed by a reference and do pointer arithmetics on it e.g. &obj + 5). You can perform arithmetics with pointers, like post increment, pre increment. Pointers can iterate over an array, you can use ++ to go to the next item that a pointer is pointing to, and + 4 to go to the 5th element. This is no matter what size the object is that the pointer points to.
Regardless of how a reference is implemented, a reference has the same memory address as the item it references. A pointer is a variable that holds a memory address.
References cannot be stuffed into an array. Pointers can be stuffed into an array.
A reference can be used directly. A pointer needs to be dereferenced with * to access the memory location it points to.
A reference to a class/struct uses . to access its members. A pointer to a class/struct uses -> to access its members.
There is one other situation in which you should use a reference, and that's when you're implementing certain operators. The most common example is operator[]. This operator typically needs to return something than can be used as the target of an assignment.
    vector <int> v(10);  // create an int vector of size 10;
    v[5] = 10;          // the target of this assignment
                        // is the return value of operator[]
    
If operator[] returned a pointer, this last statement would have to be written this way:
    *v[5] = 10;
    
But this makes it look like v is a vector of pointers, which it's not. For this reason, you'll almost always want operator[] to return a reference.
 

As a general rule,
Use references in function parameters and return types to define useful and self-documenting interfaces.
Use pointers to implement algorithms and data structures.

No comments:

Post a Comment