[c++] Pointer vs. Reference

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?

This question is related to c++ variables pointers reference

The answer is


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...


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);
}

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.
  2. 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.

  3. If a function argument is an out-value, then pass it by reference.

    • Rationale: We don't want to break item 2...
  4. 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.

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


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.


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);
}

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.


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?"


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


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.

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.


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.


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.


Examples related to c++

Method Call Chaining; returning a pointer vs a reference? How can I tell if an algorithm is efficient? Difference between opening a file in binary vs text How can compare-and-swap be used for a wait-free mutual exclusion for any shared data structure? Install Qt on Ubuntu #include errors detected in vscode Cannot open include file: 'stdio.h' - Visual Studio Community 2017 - C++ Error How to fix the error "Windows SDK version 8.1" was not found? Visual Studio 2017 errors on standard headers How do I check if a Key is pressed on C++

Examples related to variables

When to create variables (memory management) How to print a Groovy variable in Jenkins? What does ${} (dollar sign and curly braces) mean in a string in Javascript? How to access global variables How to initialize a variable of date type in java? How to define a variable in a Dockerfile? Why does foo = filter(...) return a <filter object>, not a list? How can I pass variable to ansible playbook in the command line? How do I use this JavaScript variable in HTML? Static vs class functions/variables in Swift classes?

Examples related to pointers

Method Call Chaining; returning a pointer vs a reference? lvalue required as left operand of assignment error when using C++ Error: stray '\240' in program Reference to non-static member function must be called How to convert const char* to char* in C? Why should I use a pointer rather than the object itself? Function stoi not declared C pointers and arrays: [Warning] assignment makes pointer from integer without a cast Constant pointer vs Pointer to constant How to get the real and total length of char * (char array)?

Examples related to reference

Method Call Chaining; returning a pointer vs a reference? When to create variables (memory management) Reference to non-static member function must be called Cannot find reference 'xxx' in __init__.py - Python / Pycharm c++ "Incomplete type not allowed" error accessing class reference information (Circular dependency with forward declaration) C++ initial value of reference to non-const must be an lvalue Dependent DLL is not getting copied to the build output folder in Visual Studio How to write to error log file in PHP How to reference Microsoft.Office.Interop.Excel dll? Linker Error C++ "undefined reference "