Pointer vs. Reference

C++VariablesPointersReference

C++ Problem Overview


What would be better practice when giving a function the original variable to work with:

unsigned long x = 4;

void func1(unsigned long& val) {
     val = 5;            
}
func1(x);

or:

void func2(unsigned long* val) {
     *val = 5;
}
func2(&x);

IOW: Is there any reason to pick one over another?

C++ Solutions


Solution 1 - C++

My rule of thumb is:

Use pointers if you want to do pointer arithmetic with them (e.g. incrementing the pointer address to step through an array) or if you ever have to pass a NULL-pointer.

Use references otherwise.

Solution 2 - C++

I really think you will benefit from establishing the following function calling coding guidelines:

  1. As in all other places, always be const-correct.
  • Note: This means, among other things, that only out-values (see item 3) and values passed by value (see item 4) can lack the const specifier.
  1. Only pass a value by pointer if the value 0/NULL is a valid input in the current context.
  • Rationale 1: As a caller, you see that whatever you pass in must be in a usable state.

  • Rationale 2: As called, you know that whatever comes in is in a usable state. Hence, no NULL-check or error handling needs to be done for that value.

  • Rationale 3: Rationales 1 and 2 will be compiler enforced. Always catch errors at compile time if you can.

  1. If a function argument is an out-value, then pass it by reference.
  • Rationale: We don't want to break item 2...
  1. Choose "pass by value" over "pass by const reference" only if the value is a POD (Plain old Datastructure) or small enough (memory-wise) or in other ways cheap enough (time-wise) to copy.
  • Rationale: Avoid unnecessary copies.
  • Note: small enough and cheap enough are not absolute measurables.

Solution 3 - C++

This ultimately ends up being subjective. The discussion thus far is useful, but I don't think there is a correct or decisive answer to this. A lot will depend on style guidelines and your needs at the time.

While there are some different capabilities (whether or not something can be NULL) with a pointer, the largest practical difference for an output parameter is purely syntax. Google's C++ Style Guide (https://google.github.io/styleguide/cppguide.html#Reference_Arguments), for example, mandates only pointers for output parameters, and allows only references that are const. The reasoning is one of readability: something with value syntax should not have pointer semantic meaning. I'm not suggesting that this is necessarily right or wrong, but I think the point here is that it's a matter of style, not of correctness.

Solution 4 - C++

Pointers

  • A pointer is a variable that holds a memory address.

  • A pointer declaration consists of a base type, an *, and the variable name.

  • A pointer can point to any number of variables in lifetime

  • A pointer that does not currently point to a valid memory location is given the value null (Which is zero)

     BaseType* ptrBaseType;
     BaseType objBaseType;
     ptrBaseType = &objBaseType;
    
  • The & is a unary operator that returns the memory address of its operand.

  • Dereferencing operator (*) is used to access the value stored in the variable which pointer points to.

        int nVar = 7;
        int* ptrVar = &nVar;
        int nVar2 = *ptrVar;
    

Reference

  • A reference (&) is like an alias to an existing variable.

  • A reference (&) is like a constant pointer that is automatically dereferenced.

  • It is usually used for function argument lists and function return values.

  • A reference must be initialized when it is created.

  • Once a reference is initialized to an object, it cannot be changed to refer to another object.

  • You cannot have NULL references.

  • A const reference can refer to a const int. It is done with a temporary variable with value of the const

      int i = 3;    //integer declaration
      int * pi = &i;    //pi points to the integer i
      int& ri = i;    //ri is refers to integer i – creation of reference and initialization
    

enter image description here

enter image description here

Solution 5 - C++

You should pass a pointer if you are going to modify the value of the variable. Even though technically passing a reference or a pointer are the same, passing a pointer in your use case is more readable as it "advertises" the fact that the value will be changed by the function.

Solution 6 - C++

If you have a parameter where you may need to indicate the absence of a value, it's common practice to make the parameter a pointer value and pass in NULL.

A better solution in most cases (from a safety perspective) is to use boost::optional. This allows you to pass in optional values by reference and also as a return value.

// Sample method using optional as input parameter
void PrintOptional(const boost::optional<std::string>& optional_str)
{
    if (optional_str)
    {
       cout << *optional_str << std::endl;
    }
    else
    {
       cout << "(no string)" << std::endl;
    }
}

// Sample method using optional as return value
boost::optional<int> ReturnOptional(bool return_nothing)
{
    if (return_nothing)
    {
       return boost::optional<int>();
    }

    return boost::optional<int>(42);
}

Solution 7 - C++

Use a reference when you can, use a pointer when you have to. From C++ FAQ: "When should I use references, and when should I use pointers?"

Solution 8 - C++

A reference is an implicit pointer. Basically you can change the value the reference points to but you can't change the reference to point to something else. So my 2 cents is that if you only want to change the value of a parameter pass it as a reference but if you need to change the parameter to point to a different object pass it using a pointer.

Solution 9 - C++

Consider C#'s out keyword. The compiler requires the caller of a method to apply the out keyword to any out args, even though it knows already if they are. This is intended to enhance readability. Although with modern IDEs I'm inclined to think that this is a job for syntax (or semantic) highlighting.

Solution 10 - C++

Pass by const reference unless there is a reason you wish to change/keep the contents you are passing in.

This will be the most efficient method in most cases.

Make sure you use const on each parameter you do not wish to change, as this not only protects you from doing something stupid in the function, it gives a good indication to other users what the function does to the passed in values. This includes making a pointer const when you only want to change whats pointed to...

Solution 11 - C++

Pointers:

  • Can be assigned nullptr (or NULL).
  • At the call site, you must use & if your type is not a pointer itself, making explicitly you are modifying your object.
  • Pointers can be rebound.

References:

  • Cannot be null.
  • Once bound, cannot change.
  • Callers don't need to explicitly use &. This is considered sometimes bad because you must go to the implementation of the function to see if your parameter is modified.

Solution 12 - C++

A reference is similar to a pointer, except that you don’t need to use a prefix ∗ to access the value referred to by the reference. Also, a reference cannot be made to refer to a different object after its initialization.

References are particularly useful for specifying function arguments.

for more information see "A Tour of C++" by "Bjarne Stroustrup" (2014) Pages 11-12

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJack RezaView Question on Stackoverflow
Solution 1 - C++Nils PipenbrinckView Answer on Stackoverflow
Solution 2 - C++Johann GerellView Answer on Stackoverflow
Solution 3 - C++Aaron N. TubbsView Answer on Stackoverflow
Solution 4 - C++Saurabh RaootView Answer on Stackoverflow
Solution 5 - C++Max CaceresView Answer on Stackoverflow
Solution 6 - C++Kiley HykawyView Answer on Stackoverflow
Solution 7 - C++RezaPlusPlusView Answer on Stackoverflow
Solution 8 - C++View Answer on Stackoverflow
Solution 9 - C++Daniel EarwickerView Answer on Stackoverflow
Solution 10 - C++NotJarvisView Answer on Stackoverflow
Solution 11 - C++Germán DiagoView Answer on Stackoverflow
Solution 12 - C++amirfgView Answer on Stackoverflow