As a C++ programmer I find that a lot of people moving over from plain C to C++, as well as people beginning to learn C++ seem to learn the vast majority of differences but for some reason miss references.
I think that many people read the section of their C++ book on references that says they are a bit like pointers, then decide that they have got on with pointers fine in the past and according to the book there isn't much difference so they won't bother going any further with them. It's such a shame really because references are so much more than pointers. In some ways they can even be used to promote safer code and design rules for software.
In this article I will be going through the list below explaining references and there relationship with pointers, potential pitfalls and use as a design tool.
- Relationship with pointers
- Things to remember when using references
- References as a design tool
- Advantages of references
Relationship with pointers
A pointer can be used in two ways, it can be used to move around in memory changing the location it is pointing to using pointer arithmetic or it can be used to access the actual data at the memory address (de-referencing). References however can only be used like de-referenced pointers, they are assigned an area of memory on creation and that's the only location they are allowed to point to. Once the assignment has taken place the reference will behave as if it is the data it is pointing to.
A reference can never be null itself like a pointer can, however the area of memory it points to could be invalid. How exactly this happens and how to avoid it are explained in the next section.
Things to remember when using references
References should be used when you can guarantee the life time of the object the reference is pointing to. If you can do this then the reference should never become invalid. The major reasons for references becoming invalid are for them to be assigned to memory that has been newed and the life time of that memory can not be guaranteed. When ever you assign anything to a reference you are making a contract with yourself and any code that uses your code that what ever the reference is pointing to will be in existence for the duration of its use.
Quite often if a crash occurs inside a function that uses references as its parameters its usually the fault of the function that called it not checking to make sure its data is valid. If the variables being passed in are allocated on the stack then this should never be a problem as they have guaranteed life time, however if it is passed data from the heap it could be null. As a general rule of thumb a null pointer should never be de-referenced and assigned to anything, this is very dangerous and can cause all kinds of crashes. It is also about the only way you would cause a reference to point to invalid memory. Threading can also cause an issue if the memory the reference was allocated to gets deleted by one thread while it's in use in another. However if situations like this occur it's more than likely that there is a more deep routed problem with the code as situations like that shouldn't occur with proper locking in place.
As a general rule, if the object you are passing around has a guaranteed life time then use a reference, otherwise use a pointer.
References as a design tool
References are a very powerful design tool. If a function you have made returns a reference then other programmers will know that they shouldn't have to worry about the contents of that reference all of a sudden disappearing. They will also know that the function will always return them some form of valid data, as a reference can not be null. If you use references as parameters to a function it lets the programmer using it know that they have to take responsibility to make sure that the data passed in is valid, and will stay valid for the duration of the function call.
References can be used to add more safety to code as well. For example you can pass an array of objects to a function via a pointer and you don't have to specify how big the array is. This could cause buffer overflows if you try and go too far through the array. References won't let you do this. If you want a function to take an array as a reference you have to specify the size of the array in the function declaration. This has the disadvantage of having to know exactly how big the array will be when writing the code, but it has the advantage of allowing the compiler to tell you if the array being passed to the function is the wrong size, instead of the program crashing.
Advantages of references
References share the majority of the same advantages as pointers. They are much more efficient to be passes around as parameters to functions especially if the object they point to is large, as references like pointers will not incur the copy overhead that would happen when passing by value. They have the extra advantage over pointers of; if it is used as a parameter it can be used within the function as if it was passed by value. This usually means that code can be kept cleaner and easier to read, as sometimes lots of pointer notation and de-referencing can look messy.
While this has been a quick overview of the features of references as well as some of the things to look out for when using them I hope it encourages people who have been putting off using them for one reason or another to start using them now. I will probably post some more short articles on using references in certain situations in the future. All comments are welcome.

1 comments:
Would it be possible for you to demonstrate on a small example how to use references for passing an array of objects to a function?
Post a Comment