How does a handle differ from a pointer to an object and also why can't we have a reference to a reference?
A handle is usually an opaque reference to an object. The type of the handle is unrelated to the element referenced. Consider for example a file descriptor returned by open() system call. The type is int but it represents an entry in the open files table. The actual data stored in the table is unrelated to the int that was returned by open() freeing the implementation from having to maintain compatibility (i.e. the actual table can be refactored transparently without affecting user code. Handles can only be used by functions in the same library interface, that can remap the handle back to the actual object.
A pointer is the combination of an address in memory and the type of the object that resides in that memory location. The value is the address, the type of the pointer tells the compiler what operations can be performed through that pointer, how to interpret the memory location. Pointers are transparent in that the object referenced has a concrete type that is present from the pointer. Note that in some cases a pointer can serve as a handle (a void* is fully opaque, a pointer to an empty interface is just as opaque).
References are aliases to an object. That is why you cannot have a reference to a reference: you can have multiple aliases for an object, but you cannot have an alias of an alias. As with pointers references are typed. In some circumstances, references can be implemented by the compiler as pointers that are automatically dereferenced on use, in some other cases the compiler can have references that have no actual storage. The important part is that they are aliases to an object, they must be initialized with an object and cannot be reseated to refer to a different object after they are initialized. Once they are initialized, all uses of the reference are uses of the real object.
To even ask the question, "why can't we have a reference to a reference?" means you don't understand what a reference is.
A reference is another name for an object; nothing more. If I have an object stored in variable X, I can create a variable Y that is a reference to this object. They're both talking about the same object, so what exactly would it mean to have a reference to Y? It wouldn't be any different from having a reference to X because they're all referencing the same thing.
A "handle" does not have a definition as far as the C++ language is concerned. Generally speaking, a "handle" is a construct of some form which represents some sort of resource. You get it from some API that creates the resource. You call functions that take the handle as a parameter in order to query the state of the resource or modify it. And when you're done with it, you give it to some other API function.
A pointer could be a handle. A reference could be a handle. An object could be a handle. An integer could be a handle. It all depends on what the system that implements the handle wants to do with it.
A handle is also sometimes called a "magic cookie". Its just a value of some opaque type that identifies an object. In some cases it's implemented as an actual pointer, so if you cast it to a pointer to the correct type, you can dereference it and work with whatever sort of thing it points at.
In other cases, it'll be implemented as something other than a pointer -- for example, you might have a table of objects of that type, and the handle is really just an index into that table. Unless you know the base address of the table, you can't do much of anything with the index.
C++ simply says that references to references aren't possible. There isn't much in the way of a "why" -- if they'd wanted to badly enough, they undoubtedly could have allowed it (as well as arrays of references, for that matter). The decision was made, however, that it was best to restrict references (a lot), so that's what they did.
The difference is the context.
Basic meaning of a handle is that it refers to some object in very limited context; eg. an OS can keep only 20 files opened for a user or pid. A pointer refers to the same object in the context of "memory". And reference is an "alias" to an object -- it refers to an object in the context of source code; thus reference to a reference doesn't exists as a reference already "is" the object.
Related
I'd like to work out conventions on passing parameters to functions/methods. I know it's a common issue and it has been answered many times, but I searched a lot and found nothing that fully satisfies me.
Passing by value is obvious and I won't mention this. What I came up with is:
Passing by non-const reference means, that object is MODIFIED
Passing by const reference means, that object is USED
Passing by pointer means, that a reference to object is going to be STORED. Whether ownership is passed or not will depend on the context.
It seems to be consistent, but when I want to pick heap-allocated object and pass it to 2. case parameter, it'd look like this:
void use(const Object &object) { ... }
//...
Object *obj = getOrCreateObject();
use(*obj);
or
Object &obj = *getOrCreateObject();
use(obj);
Both look weird to me. What would you advise?
PS I know that one should avoid raw pointers and use smart instead (easier memory managment and expressiveness in ownership) and it can be the next step in refactoring the project I work on.
You can use these conventions if you like. But keep in mind that you cannot assume conventions when dealing with code written by other people. You also cannot assume that people reading your code are aware of your conventions. You should document an interface with comments when it might be ambiguous.
Passing by pointer means, that object is going to be STORED. Who's its owner will depend on the context.
I can think of only one context where the ownership of a pointer argument should transfer to the callee: Constructor of a smart pointer.
Besides possible intention of storing, a pointer argument can alternatively have the same meaning as a reference argument, with the addition that the argument is optional. You typically cannot represent an optional argument with a reference since they cannot be null - although with custom types you could use a reference to a sentinel value.
Both look weird to me. What would you advise?
Neither look weird to me, so my advise is to get accustomed.
The main problem with your conventions is that you make no allowance for the possibility of interfacing to code (e.g. written by someone else) that doesn't follow your conventions.
Generally speaking, I use a different set of conventions, and rarely find a need to work around them. (The main exception will be if there is a need to use a pointer to a pointer, but I rarely need to do that directly).
Passing by non-const reference is appropriate if ANY of the following MAY be true;
The object may be changed;
The object may be passed to another function by a non-const reference [relevant when using third party code by developers who choose to omit the const - which is actually something a lot of beginners or lazy developers do];
The object may be passed to another function by a non-const pointer [relevant when using third party code be developers who choose to omit the const, or when using legacy APIs];
Non-const member functions of the object are called (regardless of whether they change the object or not) [also often a consideration when using third-party code by developers who prefer to avoid using const].
Conversely, const references may be passed if ALL of the following are true;
No non-mutable members of the object are changed;
The object is only passed to other functions by const reference, by const pointer, or by value;
Only const member functions of the object are called (even if those members are able to change mutable members.
I'll pass by value instead of by const reference in cases where the function would copy the object anyway. (e.g. I won't pass by const reference, and then construct a copy of the passed object within the function).
Passing non-const pointers is relevant if it is appropriate to pass a non-const reference but there is also a possibility of passing no object (e.g. a nullptr).
Passing const pointers is relevant if it is appropriate to pass a const reference but there is also a possibility of passing no object (e.g. a nullptr).
I would not change the convention for either of the following
Storing a reference or pointer to the object within the function for later use - it is possible to convert a pointer to a reference or vice versa. And either one can be stored (a pointer can be assigned, a reference can be used to construct an object);
Distinguishing between dynamically allocated and other objects - since I mostly either avoid using dynamic memory allocation at all (e.g. use standard containers, and pass them around by reference or simply pass iterators from them around) or - if I must use a new expression directly - store the pointer in another object that becomes responsible for deallocation (e.g. a std::smart_pointer) and then pass the containing object around.
In my opionion, they are the same. In the first part of your post, you are talking about the signature, but your example is about function call.
Q: Is pass-by-value/reference defined strictly by behavior or implementation wise in C++, and can you provide an authoritative citation?
I had a conversion with a friend about pass-by-value/reference in C++. We came to a disagreement on the definition of pass-by-value/reference. I understand that passing a pointer to a function is still pass-by-value since the value of the pointer is copied, and this copy is used in the function. Subsequently, dereferencing the pointer in the function and mutating it will modify the original variable. This is where the disagreement appears.
His stance: Just because a pointer value was copied and passed to the function, performing operations on the dereferenced pointer has the ability to affect the original variable, so it has the behavior of pass-by-reference, passing a pointer to a function.
My stance: Passing a pointer to a function does copy the value of the pointer, and operations in the function may affect the original variable; however, just because it may affect the original, this behavior does not constitute it to be pass-by-reference since it is the implementation of the language that is what defines these terms, pass-by-value/reference.
Quoting from the definition given by the highest voted answer here: Language Agnostic
Pass by Reference
When a parameter is passed by reference, the caller and the callee use the same variable for the parameter. If the callee modifies the parameter variable, the effect is visible to the caller's variable.
Pass by Value
When a parameter is passed by value, the caller and callee have two independent variables with the same value. If the callee modifies the parameter variable, the effect is not visible to the caller.
I still have an ambiguous feeling after reading these. For example, the pass by value/reference quotes can support either of our claims. Can anyone clear up the definitions of whether these definition stem from behavior or implementation and provide a citation? Thanks!
Edit: I should be a little more careful of my vocabulary. Let me extend my question with a clarification. What I mean when questioning pass-by-reference is not talking purely about the C++ implementation of & reference, but instead also the theory. In C++, is it that the & pass-by-reference is true PBR because not only can it modify the original value, but also the memory address of the value. This leads to this, example with pointers also count as PBR?
void foo(int ** bar){
*bar = *bar+(sizeof(int*));
cout<<"Inside:"<<*bar<<endl;
}
int main(){
int a = 42;
int* ptrA = &a;
cout<<"Before"<<ptrA<<endl;
foo(&ptrA);
cout<<"After:"<<ptrA<<endl;
}
The output would be that After ptrA is equal to Inside, meaning that not only can the function modify a, but ptrA. Because of this, does this define call-by-reference as a theory: being able to not only modify the value, but the memory address of the value. Sorry for the convoluted example.
You talk a lot about pointers here, which they are indeed passed by value most of the time, but you don't mention actual C++ references, which are actual references.
int a{};
int& b = a;
// Prints true
std::cout << std::boolalpha << (&b == &a) << std::endl;
Here, as you can see, both variables have the same address. Put it simply, especially in this case, references act as being another name for a variable.
References in C++ are special. They are not objects, unlike pointers. You cannot have an array of references, because it would require that references has a size. Reference are not required to have a storage at all.
What about actually passing a variable by reference then?
Take a look at this code:
void foo(int& i) {
i++;
}
int main() {
int i{};
foo(i);
// prints 1
std::cout << i << std::endl;
}
In that particular case, the compiler must have a way to send to which variable the reference is bound. Indeed references are not required to have any storage, but they are not required to not have one either. In this case, if optimizations are disabled, it is most likely that the compiler implements the behavior of references using pointers.
Of course, if optimizations are enabled, it may skip the passing and completely inline the function. In that case, the reference don't exist, or don't have any storage, because the original variable will be used directly.
Other similar optimization happens with pointers too, but that's not the point: The point is, the way references are implemented is implementation defined. They are most likely implemented in term of pointers, but they are not forced to, and the way a reference is implemented may vary from case to case. The behavior of references are defined by the standard, and really is pass-by-reference.
What about pointers? Do they count as passing by reference?
I would say no. Pointers are objects, just like int, or std::string. You can even pass a reference to a pointer, allowing you to change the original pointer.
However, pointers do have reference semantics. They are not reference indeed, just like std::reference_wrapper is not a reference either, but they have reference semantics. I wouldn't call passing a pointer "passing by reference", because you don't have an actual reference, but you indeed have reference semantics.
A lot of things have reference semantics, pointers, std::reference_wrapper, a handle to a resource, even GLuint, which are handle to an opengl object, all have reference semantics, but they are not references. You don't have a reference to the actual object, but you can change the pointed-to object through these handles.
There are other good articles and answers you can read about. They are all very informative about value and reference semantics.
isocpp.org: Reference and Value Semantics
Andrzej's C++ blog: Value semantics
Stack Overflow: What are the differences between a pointer variable and a reference variable in C++?
Passing by value/reference (you forgot one which is passing the address to the location in memory by using a pointer) is part of the implementation of C++.
There is one more way to pass variables to functions, and that is by address. Passing an argument by address involves passing the address of the argument variable (using a pointer) rather than the argument variable itself. Because the argument is an address, the function parameter must be a pointer. The function can then dereference the pointer to access or change the value being pointed to.
Take a look here at what I have always thought to be an authoritative Source: Passing Arguments by Address.
You're correct in regards to a value being copied when passing by value. This is the default behavior in C++. The advantage of passing by value into a function is that the original value cannot be changed by the function when the value is passed into it and this prevents any unwanted bugs and/or side effects when changing the value of an argument.
The problem with passing by Value is that you will incur a huge performance penalty if you pass an entire struct or class many times into your function as you will be passing entire copies of the value you are trying to pass AND in the case of a mutator method in a class, you will not be able to change the original values and will therefore end up creating multiple copies of the data you are trying to modify because you will be forced to return the new value from the function itself instead of from the location in memory where the data structure resides. This is just completely inefficient.
You only want to pass by value when you don't have to change the value of the argument.
Here is a good source on the topic of Passing Arguments by Value.
Now, you will want to use the "Pass by Reference" behavior when you do need to change the value of an argument in the case of arrays, Classes, or structs. It is more efficient to change the value of a data structure by Passing a Reference to the location in memory where the data structure resides into the function. This has the benefit that you will not have to return the new value from the function but rather, the function can then change the value of the reference you have given it directly where it resides in memory.
Take a look here to read more about about Passing an Argument by Reference.
EDIT: In regards to the issue as to whether or not you are passing a non-const by reference or by value when using a pointer, it seems to me the answer is clear. When using a pointer to a non-const, it is neither. When passing a pointer as an argument to a function, you in fact are "Passing the Value" of the ADDRESS into the function and since it is a copy of the ADDRESS of the location in memory where the non-const resides, then you are able to change the Value of the data at that location and not the value of the pointer itself. If you do not want to change the value of the data located at the address pointed to by the pointer being passed by value as an argument into your function, it is good form to make the pointer to an argument a const since the function will not be changing the value of the data itself.
Hope that makes sense.
References are different from pointers. The main reason references were introduced is to support Operator Overloading. C++ is derived from C and during the process, Pointers were inherited from C. As Stroustrup says:
C++ inherited pointers from C, so I couldn't remove them without causing serious compatibility problems.
So, effectively there are three different ways of parameters passing:
Pass by value
Pass by reference &
Pass by pointers.
Now, pass by pointer has the same effect as pass by reference. So how to decide on what you want to use? Going back to what Stroustrup said:
That depends on what you are trying to achieve:
If you want to change the object passed, call by reference or use a pointer; e.g. void f(X&); or void f(X*);
If you don't want to change the object passed and it is big, call by const reference; e.g. void f(const X&);
Otherwise, call by value; e.g. void f(X);
Ref: http://www.stroustrup.com/bs_faq2.html#pointers-and-references
Those terms are about the variable that is passed, in this case the pointer. If you pass a pointer to a function then the variable that is passed is the pointer - holding the address of the object - to an object and not the object it points to.
If you pass a pointer by value then chaning the object it is pointing to in the function would not affect the pointer that was passed to the function.
If you pass the pointer by reference then you can change in the function where the pointer is pointing to and it would modifiy the pointer that was passed to this function.
Thats how it is defined. Otherwise you could argue that if you have a global std::map<int,SomeObject> and you pass an int as key to the object, would also be a pass by reference because you can modify the objects in that global map, and the caller would see those changes. Because this int is also just a pointer to an object.
I understand the syntax and general semantics of pointers versus references, but how should I decide when it is more-or-less appropriate to use references or pointers in an API?
Naturally some situations need one or the other (operator++ needs a reference argument), but in general I'm finding I prefer to use pointers (and const pointers) as the syntax is clear that the variables are being passed destructively.
E.g. in the following code:
void add_one(int& n) { n += 1; }
void add_one(int* const n) { *n += 1; }
int main() {
int a = 0;
add_one(a); // Not clear that a may be modified
add_one(&a); // 'a' is clearly being passed destructively
}
With the pointer, it's always (more) obvious what's going on, so for APIs and the like where clarity is a big concern are pointers not more appropriate than references? Does that mean references should only be used when necessary (e.g. operator++)? Are there any performance concerns with one or the other?
EDIT (OUTDATED):
Besides allowing NULL values and dealing with raw arrays, it seems the choice comes down to personal preference. I've accepted the answer below that references Google's C++ Style Guide, as they present the view that "References can be confusing, as they have value syntax but pointer semantics.".
Due to the additional work required to sanitise pointer arguments that should not be NULL (e.g. add_one(0) will call the pointer version and break during runtime), it makes sense from a maintainability perspective to use references where an object MUST be present, though it is a shame to lose the syntactic clarity.
Use reference wherever you can, pointers wherever you must.
Avoid pointers until you can't.
The reason is that pointers make things harder to follow/read, less safe and far more dangerous manipulations than any other constructs.
So the rule of thumb is to use pointers only if there is no other choice.
For example, returning a pointer to an object is a valid option when the function can return nullptr in some cases and it is assumed it will. That said, a better option would be to use something similar to std::optional (requires C++17; before that, there's boost::optional).
Another example is to use pointers to raw memory for specific memory manipulations. That should be hidden and localized in very narrow parts of the code, to help limit the dangerous parts of the whole code base.
In your example, there is no point in using a pointer as argument because:
if you provide nullptr as the argument, you're going in undefined-behaviour-land;
the reference attribute version doesn't allow (without easy to spot tricks) the problem with 1.
the reference attribute version is simpler to understand for the user: you have to provide a valid object, not something that could be null.
If the behaviour of the function would have to work with or without a given object, then using a pointer as attribute suggests that you can pass nullptr as the argument and it is fine for the function. That's kind of a contract between the user and the implementation.
The performances are exactly the same, as references are implemented internally as pointers. Thus you do not need to worry about that.
There is no generally accepted convention regarding when to use references and pointers. In a few cases you have to return or accept references (copy constructor, for instance), but other than that you are free to do as you wish. A rather common convention I've encountered is to use references when the parameter must refer an existing object and pointers when a NULL value is ok.
Some coding convention (like Google's) prescribe that one should always use pointers, or const references, because references have a bit of unclear-syntax: they have reference behaviour but value syntax.
From C++ FAQ Lite -
Use references when you can, and pointers when you have to.
References are usually preferred over pointers whenever you don't need
"reseating". This usually means that references are most useful in a
class's public interface. References typically appear on the skin of
an object, and pointers on the inside.
The exception to the above is where a function's parameter or return
value needs a "sentinel" reference — a reference that does not refer
to an object. This is usually best done by returning/taking a pointer,
and giving the NULL pointer this special significance (references must
always alias objects, not a dereferenced NULL pointer).
Note: Old line C programmers sometimes don't like references since
they provide reference semantics that isn't explicit in the caller's
code. After some C++ experience, however, one quickly realizes this is
a form of information hiding, which is an asset rather than a
liability. E.g., programmers should write code in the language of the
problem rather than the language of the machine.
My rule of thumb is:
Use pointers for outgoing or in/out parameters. So it can be seen that the value is going to be changed. (You must use &)
Use pointers if NULL parameter is acceptable value. (Make sure it's const if it's an incoming parameter)
Use references for incoming parameter if it cannot be NULL and is not a primitive type (const T&).
Use pointers or smart pointers when returning a newly created object.
Use pointers or smart pointers as struct or class members instead of references.
Use references for aliasing (eg. int ¤t = someArray[i])
Regardless which one you use, don't forget to document your functions and the meaning of their parameters if they are not obvious.
Disclaimer: other than the fact that references cannot be NULL nor "rebound" (meaning thay can't change the object they're the alias of), it really comes down to a matter of taste, so I'm not going to say "this is better".
That said, I disagree with your last statement in the post, in that I don't think the code loses clarity with references. In your example,
add_one(&a);
might be clearer than
add_one(a);
since you know that most likely the value of a is going to change. On the other hand though, the signature of the function
void add_one(int* const n);
is somewhat not clear either: is n going to be a single integer or an array? Sometimes you only have access to (poorly documentated) headers, and signatures like
foo(int* const a, int b);
are not easy to interpret at first sight.
Imho, references are as good as pointers when no (re)allocation nor rebinding (in the sense explained before) is needed. Moreover, if a developer only uses pointers for arrays, functions signatures are somewhat less ambiguous. Not to mention the fact that operators syntax is way more readable with references.
Like others already answered: Always use references, unless the variable being NULL/nullptr is really a valid state.
John Carmack's viewpoint on the subject is similar:
NULL pointers are the biggest problem in C/C++, at least in our code. The dual use of a single value as both a flag and an address causes an incredible number of fatal issues. C++ references should be favored over pointers whenever possible; while a reference is “really” just a pointer, it has the implicit contract of being not-NULL. Perform NULL checks when pointers are turned into references, then you can ignore the issue thereafter.
http://www.altdevblogaday.com/2011/12/24/static-code-analysis/
Edit 2012-03-13
User Bret Kuhns rightly remarks:
The C++11 standard has been finalized. I think it's time in this thread to mention that most code should do perfectly fine with a combination of references, shared_ptr, and unique_ptr.
True enough, but the question still remains, even when replacing raw pointers with smart pointers.
For example, both std::unique_ptr and std::shared_ptr can be constructed as "empty" pointers through their default constructor:
http://en.cppreference.com/w/cpp/memory/unique_ptr/unique_ptr
http://en.cppreference.com/w/cpp/memory/shared_ptr/shared_ptr
... meaning that using them without verifying they are not empty risks a crash, which is exactly what J. Carmack's discussion is all about.
And then, we have the amusing problem of "how do we pass a smart pointer as a function parameter?"
Jon's answer for the question C++ - passing references to boost::shared_ptr, and the following comments show that even then, passing a smart pointer by copy or by reference is not as clear cut as one would like (I favor myself the "by-reference" by default, but I could be wrong).
It is not a matter of taste. Here are some definitive rules.
If you want to refer to a statically declared variable within the scope in which it was declared then use a C++ reference, and it will be perfectly safe. The same applies to a statically declared smart pointer. Passing parameters by reference is an example of this usage.
If you want to refer to anything from a scope that is wider than the scope in which it is declared then you should use a reference counted smart pointer for it to be perfectly safe.
You can refer to an element of a collection with a reference for syntactic convenience, but it is not safe; the element can be deleted at anytime.
To safely hold a reference to an element of a collection you must use a reference counted smart pointer.
There is problem with "use references wherever possible" rule and it arises if you want to keep reference for further use. To illustrate this with example, imagine you have following classes.
class SimCard
{
public:
explicit SimCard(int id):
m_id(id)
{
}
int getId() const
{
return m_id;
}
private:
int m_id;
};
class RefPhone
{
public:
explicit RefPhone(const SimCard & card):
m_card(card)
{
}
int getSimId()
{
return m_card.getId();
}
private:
const SimCard & m_card;
};
At first it may seem to be a good idea to have parameter in RefPhone(const SimCard & card) constructor passed by a reference, because it prevents passing wrong/null pointers to the constructor. It somehow encourages allocation of variables on stack and taking benefits from RAII.
PtrPhone nullPhone(0); //this will not happen that easily
SimCard * cardPtr = new SimCard(666); //evil pointer
delete cardPtr; //muahaha
PtrPhone uninitPhone(cardPtr); //this will not happen that easily
But then temporaries come to destroy your happy world.
RefPhone tempPhone(SimCard(666)); //evil temporary
//function referring to destroyed object
tempPhone.getSimId(); //this can happen
So if you blindly stick to references you trade off possibility of passing invalid pointers for the possibility of storing references to destroyed objects, which has basically same effect.
edit: Note that I sticked to the rule "Use reference wherever you can, pointers wherever you must. Avoid pointers until you can't." from the most upvoted and accepted answer (other answers also suggest so). Though it should be obvious, example is not to show that references as such are bad. They can be misused however, just like pointers and they can bring their own threats to the code.
There are following differences between pointers and references.
When it comes to passing variables, pass by reference looks like pass by value, but has pointer semantics (acts like pointer).
Reference can not be directly initialized to 0 (null).
Reference (reference, not referenced object) can not be modified (equivalent to "* const" pointer).
const reference can accept temporary parameter.
Local const references prolong the lifetime of temporary objects
Taking those into account my current rules are as follows.
Use references for parameters that will be used locally within a function scope.
Use pointers when 0 (null) is acceptable parameter value or you need to store parameter for further use. If 0 (null) is acceptable I am adding "_n" suffix to parameter, use guarded pointer (like QPointer in Qt) or just document it. You can also use smart pointers. You have to be even more careful with shared pointers than with normal pointers (otherwise you can end up with by design memory leaks and responsibility mess).
Any performance difference would be so small that it wouldn't justify using the approach that's less clear.
First, one case that wasn't mentioned where references are generally superior is const references. For non-simple types, passing a const reference avoids creating a temporary and doesn't cause the confusion you're concerned about (because the value isn't modified). Here, forcing a person to pass a pointer causes the very confusion you're worried about, as seeing the address taken and passed to a function might make you think the value changed.
In any event, I basically agree with you. I don't like functions taking references to modify their value when it's not very obvious that this is what the function is doing. I too prefer to use pointers in that case.
When you need to return a value in a complex type, I tend to prefer references. For example:
bool GetFooArray(array &foo); // my preference
bool GetFooArray(array *foo); // alternative
Here, the function name makes it clear that you're getting information back in an array. So there's no confusion.
The main advantages of references are that they always contain a valid value, are cleaner than pointers, and support polymorphism without needing any extra syntax. If none of these advantages apply, there is no reason to prefer a reference over a pointer.
Copied from wiki-
A consequence of this is that in many implementations, operating on a variable with automatic or static lifetime through a reference, although syntactically similar to accessing it directly, can involve hidden dereference operations that are costly. References are a syntactically controversial feature of C++ because they obscure an identifier's level of indirection; that is, unlike C code where pointers usually stand out syntactically, in a large block of C++ code it may not be immediately obvious if the object being accessed is defined as a local or global variable or whether it is a reference (implicit pointer) to some other location, especially if the code mixes references and pointers. This aspect can make poorly written C++ code harder to read and debug (see Aliasing).
I agree 100% with this, and this is why I believe that you should only use a reference when you a have very good reason for doing so.
Points to keep in mind:
Pointers can be NULL, references cannot be NULL.
References are easier to use, const can be used for a reference when we don't want to change value and just need a reference in a function.
Pointer used with a * while references used with a &.
Use pointers when pointer arithmetic operation are required.
You can have pointers to a void type int a=5; void *p = &a; but cannot have a reference to a void type.
Pointer Vs Reference
void fun(int *a)
{
cout<<a<<'\n'; // address of a = 0x7fff79f83eac
cout<<*a<<'\n'; // value at a = 5
cout<<a+1<<'\n'; // address of a increment by 4 bytes(int) = 0x7fff79f83eb0
cout<<*(a+1)<<'\n'; // value here is by default = 0
}
void fun(int &a)
{
cout<<a<<'\n'; // reference of original a passed a = 5
}
int a=5;
fun(&a);
fun(a);
Verdict when to use what
Pointer: For array, linklist, tree implementations and pointer arithmetic.
Reference: In function parameters and return types.
The following are some guidelines.
A function uses passed data without modifying it:
If the data object is small, such as a built-in data type or a small structure, pass it by value.
If the data object is an array, use a pointer because that’s your only choice. Make the pointer a pointer to const.
If the data object is a good-sized structure, use a const pointer or a const
reference to increase program efficiency.You save the time and space needed to
copy a structure or a class design. Make the pointer or reference const.
If the data object is a class object, use a const reference.The semantics of class design often require using a reference, which is the main reason C++ added
this feature.Thus, the standard way to pass class object arguments is by reference.
A function modifies data in the calling function:
1.If the data object is a built-in data type, use a pointer. If you spot code
like fixit(&x), where x is an int, it’s pretty clear that this function intends to modify x.
2.If the data object is an array, use your only choice: a pointer.
3.If the data object is a structure, use a reference or a pointer.
4.If the data object is a class object, use a reference.
Of course, these are just guidelines, and there might be reasons for making different
choices. For example, cin uses references for basic types so that you can use cin >> n
instead of cin >> &n.
Your properly written example should look like
void add_one(int& n) { n += 1; }
void add_one(int* const n)
{
if (n)
*n += 1;
}
That's why references are preferable if possible
...
References are cleaner and easier to use, and they do a better job of hiding information.
References cannot be reassigned, however.
If you need to point first to one object and then to another, you must use a pointer. References cannot be null, so if any chance exists that the object in question might be null, you must not use a reference. You must use a pointer.
If you want to handle object manipulation on your own i.e if you want to allocate memory space for an object on the Heap rather on the Stack you must use Pointer
int *pInt = new int; // allocates *pInt on the Heap
In my practice I personally settled down with one simple rule - Use references for primitives and values that are copyable/movable and pointers for objects with long life cycle.
For Node example I would definitely use
AddChild(Node* pNode);
Just putting my dime in. I just performed a test. A sneeky one at that. I just let g++ create the assembly files of the same mini-program using pointers compared to using references.
When looking at the output they are exactly the same. Other than the symbolnaming. So looking at performance (in a simple example) there is no issue.
Now on the topic of pointers vs references. IMHO I think clearity stands above all. As soon as I read implicit behaviour my toes start to curl. I agree that it is nice implicit behaviour that a reference cannot be NULL.
Dereferencing a NULL pointer is not the problem. it will crash your application and will be easy to debug. A bigger problem is uninitialized pointers containing invalid values. This will most likely result in memory corruption causing undefined behaviour without a clear origin.
This is where I think references are much safer than pointers. And I agree with a previous statement, that the interface (which should be clearly documented, see design by contract, Bertrand Meyer) defines the result of the parameters to a function. Now taking this all into consideration my preferences go to
using references wherever/whenever possible.
For pointers, you need them to point to something, so pointers cost memory space.
For example a function that takes an integer pointer will not take the integer variable. So you will need to create a pointer for that first to pass on to the function.
As for a reference, it will not cost memory. You have an integer variable, and you can pass it as a reference variable. That's it. You don't need to create a reference variable specially for it.
As the title itself mentions - why are pointer to a reference illegal, while the reverse is legal in C++?
A pointer needs to point to an object. A reference is not an object.
If you have a reference r, once it is initialized, any time you use r you are actually using the object to which the reference refers.
Because of this, you can't take the address of a reference to be able to get a pointer to it in the first place. Consider the following code:
int x;
int& rx = x;
int* px = ℞
In the last line, &rx takes the address of the object referred to by rx, so it's exactly the same as if you had said &x.
The high-level concept that references implement is just another name for an existing object. You can have a pointer to an object (or function), but you can't have a pointer to an object's name. For this very reason, the idea of a pointer to a reference makes no sense. In other words, references are immaterial, in general case they simply do not exist in memory. They don't exist as something that can be pointed to.
It is true that in many cases in practice references do occupy memory (and are implemented as pointers in disguise). But that just an implementation detail specific to some particular contexts. In general case references do not occupy memory, as is explicitly stated in the language specification which immediately follows from the language specification.
What would be the difference between a pointer to a reference (to the object) and a pointer to the actual object? The reference cannot be changed to refer to another object. Just use a regular pointer to the object in question.
On the other hand, a reference to a pointer, like any other reference, gives you a modifiable handle to a particular variable. It happens to be a pointer in this case.
Because a reference is not a thing that can be pointed at, which in turn is because it does not actually have to be represented anywhere in memory. References exist to give alternate names to already-existing things. You can get a pointer to the renamed thing, but that is a pointer to a value, not a pointer to a reference.
Suppose "int *&X" is legal, because reference is just another name of an object, the expression is equal to "int *X" and is not useful.
I'm having a problem with a class like this:
class Sprite {
...
bool checkCollision(Sprite &spr);
...
};
So, if I have that class, I can do this:
ball.checkCollision(bar1);
But if I change the class to this:
class Sprite {
...
bool checkCollision(Sprite* spr);
...
};
I have to do this:
ball.checkCollision(&bar1);
So, what's the difference?? It's better a way instead other?
Thank you.
In both cases you are actually passing the address of bar1 (and you're not copying the value), since both pointers (Sprite *) and references (Sprite &) have reference semantics, in the first case explicit (you have to explicitly dereference the pointer to manipulate the pointed object, and you have to explicitly pass the address of the object to a pointer parameter), in the second case implicit (when you manipulate a reference it's as if you're manipulating the object itself, so they have value syntax, and the caller's code doesn't explicitly pass a pointer using the & operator).
So, the big difference between pointers and references is on what you can do on the pointer/reference variable: pointer variables themselves can be modified, so they may be changed to point to something else, can be NULLed, incremented, decremented, etc, so there's a strong separation between activities on the pointer (that you access directly with the variable name) and on the object that it points to (that you access with the * operator - or, if you want to access to the members, with the -> shortcut).
References, instead, aim to be just an alias to the object they point to, and do not allow changes to the reference itself: you initialize them with the object they refer to, and then they act as if they were such object for their whole life.
In general, in C++ references are preferred over pointers, for the motivations I said and for some other that you can find in the appropriate section of C++ FAQ.
In terms of performance, they should be the same, because a reference is actually a pointer in disguise; still, there may be some corner case in which the compiler may optimize more when the code uses a reference instead of a pointer, because references are guaranteed not to change the address they hide (i.e., from the beginning to the end of their life they always point to the same object), so in some strange case you may gain something in performance using references, but, again, the point of using references is about good programming style and readability, not performance.
A reference cannot be null. A pointer can.
If you don't want to allow passing null pointers into your function then use a reference.
With the pointer you need to specifically let the compiler know you want to pass the address of the object, with a reference, the compiler already knows you want the ptr. Both are ok, it's a matter of taste, I personally don't like references because I like to see whats going on but thats just me.
They both do the (essentially) same thing - they pass an object to a function by reference so that only the address of the object is copied. This is efficient and means the function can change the object.
In the simple case you give they are equivalent.
Main differences are that the reference cannot be null, so you don't have to test for null in the function - but you also cannot pass a null object if the case of no object is valid.
Some people also dislike the pass by reference version because it is not obvious in the calling code that the object you pass in might be modified. Some coding standards recommend you only pass const references to functions.