C++ References
Tags: cpp, references
Published: 2019-02-05 01:37:25

C++ is backward compatible with C so it inherited pointers. A quick recap if you don't know what a pointer is: a pointer is a variable that holds the memory address of an object. Declaring a pointer involves the type of object we are pointing to and the symbol '*'.

Example:

```cpp
int value = 10;
int *ptr_value = &value;

double vaule2 = 506.305;
double *ptr_value2 = &value;
```

We have our pointer, but how do we get an object's memory address? With the ampersand symbol (&).

To access data through a pointer, we need to do what is called dereferencing. This again includes the use of the * symbol.

```cpp
printf("value: %d\n", *ptr_value);
printf("value2: %f\n, *ptr_value2);
```

Now that the recap is over, we can move onto references.

C++ introduced references as an alternative to pointers. References were designed to be simpler, safer, and easier to read when in use. To create a reference is similar to how we declare a pointer. First, we need the type and the symbol '&'.

```cpp
int value = 200;
int &ref_value = value;
```

Notice we don't have anything extra on the right-hand side as we had with pointers. The only extra symbol in this statement is the & symbol on the left.

Another benefit is obvious when it is time to retrieve value from the reference:

```cpp
std::cout << ref_value << "\n";
```

There are no extra symbols cluttering the code. Viewing small examples of dereferenced pointers may not show the cognitive burden that may be placed on someone when viewing a larger block of code that has several dereferences going on in a short amount of time.

References, as aforementioned, are safer. Going back to pointers for a moment, a pointer can be within a state of "invalidness". This could mean two things:

1. The pointer is declared but has no initializer and is subsequently default-initialized

Within local scope, if a variable is not provided with an initial value at creation, a garbage value is left there. Most likely, it was some value left over from some memory previously that we are now occupying. Accessing a default-initialized object is undefined behavior and dereferencing a default-initialized pointer is also undefined behavior.

2. Null Pointers

A null pointer is a special kind of pointer. Usually, it is a way to say, "Hey, I'm not in use right now, but I am still explicitly initialized!". Null pointers have a place in API design. Many C functions that return a pointer may instead return a null pointer on error. Despite it being "safer" than the previous type of invalid pointer, dereferencing a null pointer is undefined behavior.

At the creation of a reference, it must have an initial value to bind. Failure to do so is a compile time error. Also, a reference is bound to one value for its entire lifetime.

However, references have their weaknesses, too. Like pointers, a reference can "dangle": referring to a space of memory that is freed.

Example:

```cpp
int &return_five()
{
    int value = 5;
    return &value;
}

int some_value = return_five();
std::cout << some_value << '\n'; // undefined behavior
```

`return_five()` is a function that creates a variable and returns it. This may appear innocent to the inexperienced but this program is in error. This value being returned is created on the stack and when the function returns, the stack frame is destroyed and so is the variable inside.

By the time we return the main function, the reference `some_value` is now referring to freed memory and is a dangling reference.

## The Conclusion

References, in theory, are a better alternative to pointers in some regards. Providing a simpler syntax at creation and accessing bounded values. The restraints in place eliminate some of the problems that using pointers may arise.