Difference Between Pointer to a Reference and Reference to a Pointer

Difference between pointer to a reference and reference to a pointer

First, a reference to a pointer is like a reference to any other variable:

void fun(int*& ref_to_ptr)
{
ref_to_ptr = 0; // set the "passed" pointer to 0
// if the pointer is not passed by ref,
// then only the copy(parameter) you received is set to 0,
// but the original pointer(outside the function) is not affected.
}

A pointer to reference is illegal in C++, because -unlike a pointer- a reference is just a concept that allows the programmer to make aliases of something else. A pointer is a place in memory that has the address of something else, but a reference is NOT.

Now the last point might not be crystal clear, if you insist on dealing with references as pointers. e.g.:

int x;
int& rx = x; // from now on, rx is just like x.
// Unlike pointers, refs are not real objects in memory.
int* p = &x; // Ok
int* pr = ℞ // OK! but remember that rx is just x!
// i.e. rx is not something that exists alone, it has to refer to something else.
if( p == pr ) // true!
{ ... }

As you can see from the above code, when we use the reference, we are not dealing with something separated from what it refers to. So, the address of a reference is just the address of what it refers to. Thats why there is no such thing called the address of the reference in terms of what you are talking about.

When to use references vs. pointers

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:

  1. if you provide nullptr as the argument, you're going in undefined-behaviour-land;
  2. the reference attribute version doesn't allow (without easy to spot tricks) the problem with 1.
  3. 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.

Difference between pointer-to-pointer vs reference-to-pointer (C++)

The first example is that of a reference to a pointer, ie. a reference to a type IEnumWbemClassObject*:

HRESULT Query ( IN BSTR sQuery, OUT IEnumWbemClassObject* &pEnumerator );

Therefore if pEnumerator is declared as a IEnumWbemClassObject* (which I'm assuming it is), you don't need to explicitly pass the address of pEnumerator to the function or dereference the variable inside the function in order to change where pEnumerator points (which would otherwise be required with an argument of IEnumWbemClassObject**).

A reference to a pointer has the same behaviour as a reference to any other type, just think of the above example as being a "reference to a pointer" and not a "pointer to a reference." There's no such thing as a pointer to a reference.

What is the difference between a C# Reference and a Pointer?

C# references can, and will be relocated by garbage collector but normal pointers are static. This is why we use fixed keyword when acquiring a pointer to an array element, to prevent it from getting moved.

EDIT: Conceptually, yes. They are more or less the same.

What is the difference between: Handle, Pointer and 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.

How is a reference different from a pointer in implementation?

Most references are implemented using a pointer variable i.e. a reference usually takes up one word of memory. However, a reference that is used purely locally can - and often is - eliminated by the optimizer. For example:

  struct S { int a, int b[100]; };  
void do_something(const vector<S>& v)
{
for (int i=0; i<v.size(); ++i) {
int*& p = v[i].b;
for (int j=0; j<100; ++j) cout <<p[j];
}

In this case, p needs not be stored in memory (maybe it just exists in a register, maybe it disappears into the instructions).



Related Topics



Leave a reply



Submit