7.4 — Passing arguments by address

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

Here is an example of a function that takes a parameter passed by address:

The above snippet prints:

value = 5
value = 6

As you can see, the function foo() changed the value of the argument (variable value) through pointer parameter ptr.

Pass by address is typically used with pointers, which most often are used to point to built-in arrays. For example, the following function will print all the values in an array:

Here is an example program that calls this function:

This program prints the following:

6 5 4 3 2 1

Remember that fixed arrays decay into pointers when passed to a function, so we have to pass the length as a separate parameter.

It is always a good idea to ensure parameters passed by address are not null pointers before dereferencing them. Dereferencing a null pointer will typically cause the program to crash. Here is our printArray() function with a null pointer check:

Passing by const address

Because printArray() doesn’t modify any of its arguments, it’s good form to make the array parameter const:

This allows us to tell at a glance that printArray() won’t modify the array argument passed in, and will ensure we don’t do so by accident.

Addresses are actually passed by value

When you pass a pointer to a function, the pointer’s value (the address it points to) is copied from the argument to the function’s parameter. In other words, it’s passed by value! If you change the function parameter’s value, you are only changing a copy. Consequently, the original pointer argument will not be changed.

Here’s a sample program that illustrates this.

tempPtr receives a copy of the address that ptr is holding. Even though we change tempPtr to point at something else (nullptr), this does not change the value that ptr points to. Consequently, this program prints:


Note that even though the address itself is passed by value, you can still dereference that address to change the argument’s value. This is a common point of confusion, so let’s clarify:

  • When passing an argument by address, the function parameter variable receives a copy of the address from the argument. At this point, the function parameter and the argument both point to the same value.
  • If the function parameter is then dereferenced to change the value being pointed to, that will impact the value the argument is pointing to, since both the function parameter and argument are pointing to the same value!
  • If the function parameter is assigned a different address, that will not impact the argument, since the function parameter is a copy, and changing the copy won’t impact the original. After changing the function parameter’s address, the function parameter and argument will point to different values, so dereferencing the parameter and changing the value will no longer affect the value pointed to by the argument.

The following program illustrates the point:

This prints:


Passing addresses by reference

The next logical question is, “What if we want to change the address an argument points to from within the function?”. Turns out, this is surprisingly easy. You can simply pass the address by reference. The syntax for doing a reference to a pointer is a little strange (and easy to get backwards). However, if you do get it backwards, the compiler will give you an error.

The following program illustrates using a reference to a pointer:

When we run the program again with this version of the function, we get:

5 ptr is null

Which shows that calling setToNull() did indeed change the value of ptr from &five to nullptr!

There is only pass by value

Now that you understand the basic differences between passing by reference, address, and value, let’s get reductionist for a moment. :)

In the lesson on references, we briefly mentioned that references are typically implemented by the compiler as pointers. This means that behind the scenes, pass by reference is essentially just a pass by address (with access to the reference doing an implicit dereference).

And just above, we showed that pass by address is actually just passing an address by value!

Therefore, we can conclude that C++ really passes everything by value! The properties of pass by address (and reference) come solely from the fact that we can dereference the passed address to change the argument, which we can not do with a normal value parameter!

Pass by address makes modifiable parameters explicit

Consider the following example:

It’s not obvious from the call to foo2() that the function can modify variable i, is it?

For this reason, some guides recommend passing all modifiable arguments by address, so that it’s more obvious from an existing function call that an argument could be modified.

However, this comes with its own set of downsides: the caller might think they can pass in nullptr when they aren’t supposed to, and you now have to rigorously check for null pointers.

We lean towards the recommendation of passing non-optional modifiable parameters by reference. Even better, avoid modifiable parameters altogether.

Pros and cons of pass by address

Advantages of passing by address:

  • Pass by address allows a function to change the value of the argument, which is sometimes useful. Otherwise, const can be used to guarantee the function won’t change the argument. (However, if you want to do this with a non-pointer, you should use pass by reference instead).
  • Because a copy of the argument is not made, it is fast, even when used with large structs or classes.
  • We can return multiple values from a function via out parameters.

Disadvantages of passing by address:

  • Because literals (excepting C-style string literals) and expressions do not have addresses, pointer arguments must be normal variables.
  • All values must be checked to see whether they are null. Trying to dereference a null value will result in a crash. It is easy to forget to do this.
  • Because dereferencing a pointer is slower than accessing a value directly, accessing arguments passed by address is slower than accessing arguments passed by value.

When to use pass by address:

  • When passing built-in arrays (if you’re okay with the fact that they’ll decay into a pointer).
  • When passing a pointer and nullptr is a valid argument logically.

When not to use pass by address:

  • When passing a pointer and nullptr is not a valid argument logically (use pass by reference).
  • When passing structs or classes (use pass by reference).
  • When passing fundamental types (use pass by value).

As you can see, pass by address and pass by reference have almost identical advantages and disadvantages. Because pass by reference is generally safer than pass by address, pass by reference should be preferred in most cases.


Prefer pass by reference to pass by address whenever applicable.

7.4a -- Returning values by value, reference, and address
7.3 -- Passing arguments by reference

215 comments to 7.4 — Passing arguments by address

  • Nirbhay

    Why doesn't this code print "NULL FOUND" ?

    • Your if-condition doesn't guard the return. Use curly braces.
      Your code isn't valid C++. Make sure you disabled compiler extensions (Lesson 0.10).

      • Nirbhay

        Still doesn't print it.

        I am using an online compiler


  • danield

    You didnt explain out parameters for pointers... or is it unnecessary

  • RyuuGP

    From the previous sub-chapter, it's said that because it's not obvious whether the arguments will be changed inside a function or not, it's not safe to pass by reference and pass by address is preferable. But in this sub-chapter it's said that passing by reference is more safe, so which one is true?

    Is it passing by reference is preferred if i want to NOT COPY the variable? That is copying struct or class can be quite heavy.
    And is passing by address preferred if i want to change the variable inside the function?

    • Is the type built-in (int, float, etc.) -> pass by value
      Does the function modify the argument or is the argument optional (Allowed to be nullptr)?
      Yes -> Pointer
      No -> const reference

        • Alex

          I added a note to the lesson about this point, as there's open debate. Google's C++ guide recommends passing modifiable arguments by address. Stroustrup and Sutter recommend passing by reference (see

  • tilon

    You write

    "When you pass a pointer to a function by address, the pointer’s value (the address it points to) is copied from the argument to the function’s parameter. In other words, it’s passed by value! If you change the function parameter’s value, you are only changing a copy."

    Then you write:

    "Because a copy of the argument is not made, it is fast, even when used with large structs or classes."

    So when I am passing argument by address is fuction creating copy of argument or no?

  • Alireza

    I can't get when passing by address changes the actual value. I'm confused !
    When does passing by address change the actual value exactly ?

  • Steven

    What's a valid use case for passing anything into a function by reference pointer? If the function changes the address of the pointer, wouldn't that just cause memory leak?

    • You wouldn't want to creates copies of a player or world, because that's slow, and you want the originals.
      You can't easily return the player, world and found-status, so you use parameters.

      Pointers to pointers are more common that references to pointers. Using a pointer to pointer in this example would make it obvious to the caller that the arguments will be modified.

  • Meghana

    So basically pass pointer by reference[taught in previous section] and pass address(with pointer) by reference[taught in this section] are same? I did not spot any differences. Can you help me with it?


  • NXPY

    "When passing a pointer and nullptr is a valid argument logically"

    I didn't understand this. Won't dereferencing a null pointer crash , thereby making a pointer with nullptr an argument bad ?

    • Let's say you have a function like this

      and you only care about whether or not @vecWorld is on the screen, but you don't want to know where it is.
      You could

      And then just don't use @vecScreen, but that's ugly. Why would you create a variable that you're not going to use anyway?
      A nicer way is checking for @nullptr inside @getScreenPosition to allow the caller to omit the argument (And possibly default to @nullptr).

  • An example of passing address by reference was shown in the previous lesson. But i was confused by its syntax and also why we need it as we passed it by address. But this lesson cleared everything. I think you should also write a note below that example that we will explore more about its use in next lesson. As i was stuck there and thought you already discussed this in the previous lessons. It will be useful for others if you do so.

  • Hexx

    OK, pointers and references are my nightmares so far. In the code below you declared the array parameter as a pointer but if an array decays to a pointer when passed to a function then do I really need to put *array as the parameter? I mean it seems kind of redundant.

    void printArray(int *array, int length)
        for (int index=0; index < length; ++index)
            std::cout << array[index] << ' ';

  • Deep Chicken

    When we pass by address, the pointer parameter points to the same address as the argument.
    When you pass by address by reference the pointer parameter has the same address as the pointer which points to a value or null. (a little bit confusing)

    My question is the following:

    Is this the same?
    Instead of having a pointer which has the same adress, we have a pointer which points to our pointer we want to change.

    Thats how we call up both functions.
    Another question.
    Is this how a reference to a pointer is implemented?

    • Hi there!

      > Is this the same?
      Yes. Pointers and references are the same thing, other than pointers being able to be nullptrs and references always having to refer to something.

      > Is this how a reference to a pointer is implemented?

  • Sam

    Am I correct in saying that pass by reference and pass by address only save memory when the passed data type is greater than 4 bytes (or 8 bytes in a 64-bit program)?

    • Alex

      Yes. But pass by reference/address isn't as much about saving memory as it is about saving time by not making unnecessary temporary copies of values. Making a copy of a 4 (or 8) byte value is fast, so using a reference or pointer isn't faster than just doing a copy. But as the size of the data being copied grows, the benefit from using a reference or pointer grows.

  • laura

    I have to one homework and I don't know like start, please help me.
    Implement the merge () function that takes as parameters two pointers to a contiguous block of doubles and their respective sizes and merge (concatenates) the first block with the second block in a new adjoining block of memory.
    The function returns a pointer to the new contiguous block of double's

  • Conor McGuigan

    Should 'tempPtr' not be 'ptr' in this comment?

  • Sagar

    When passing by address, is argument copy made as a function parameter?

  • David

    Hello! Thanks again for the great site. When I open a new command-line project in Xcode, the template looks like this:

    1) What is the purpose of putting arguments into the main function? Maybe this gets covered later, but thought I would ask.
    2) Is the parameter const char *argv[] equivalent to const char *argv? (i.e. just passing an array by address)

    • nascardriver

      Hi David!

      1) This is covered in lesson 7.13. @argv holds the strings passed to your program when running it from the command line. @argc tells you how many strings have been passed.
      2) No it's not:

  • Audrius

    Hello, is this a good way to pass changes made to an array?

    • nascardriver

      Hi Audrius!

      Your idea is good, but your implementation needs some changes.

      @X is an int pointer, what you did is the same as the code below, just more complicated

      What you should do is pass the array by reference, this way the array's size will be preserved.

      You also hardcoded the array size in your loop, that's always bad and defeats the purpose of passing an array by reference.

  • Hardik

    Why does this work ?

    In this, after execution of foo(), the variable 'x' and the local pointer 'ptr' is destroyed, so should dereferencing the pointer 'tmp1' not show undefined behaviour ? (The Same Question Goes For References !)

    • Hardik

      I think this is because as return by address is actually return by value only, so the pointer is not being passed rather it's value is being copied into tmp1. Tell me if I'm right Alex !
      But, What about references, they can be used as l-values, so they can't be returned by value, otherwise this would be illegal (foo() = /* something */), YES?
      Thanks in Advance, Alex :)

      • Alex

        Yes, the value of ptr (which is the address of variable x) is copied from foo back to main (and then assigned to tmp1). Then foo's x is destroyed. So when you dereference *tmp1, you're dereferencing an address that's no longer valid -- which will cause undefined behavior. It might still print 6 -- after all, one of the possible outcomes of undefined behavior is that you get the expected answer anyway.

        I'm not sure what you're asking about references. If you wrote the same code using references instead of pointers you'd get the same result, because you'd be referencing a variable that no longer exists (at an invalid address).

        • Hardik

          Man ! But This thing Works Everytime !
          But, yes, Returning &x causes undefined behaviour !
          And, yes for references, if i create a reference to a local variable say, int &ref = x, and, then if i return ref, it works, but if i return x, it causes again undefined behaviour.

          • Alex

            It works because the value you're pointing at or referencing hasn't been overwritten by anything yet. If you were to call another function between getting the return value and printing it, it probably wouldn't work any more.

            • Hardik

              I also thought this and even, tried this but nothing changed !
              The crashing is shown only if I return &x, and, on the other hand, if i return a pointer to x(ie. int *ptr = &x; return ptr;), it works perfectly!

  • AMG

    Came across of "C++ tr1's shared_ptr<> is a smart pointer that helps in these kinds of situations - it manages this ownership concept by keeping a reference count that tracks the number of references to the data. If the reference count is 1, then there is 1 clear owner. If the reference count is larger than 1, then ownership is shared. If the reference count is 0, then there are no more references to the data, and shared_ptr<> will delete it when the shared_ptr<> destructor is called." Wondering if you will talk about it. Thanks.

  • AMG

    Slightly modified your example from "Addresses are actually passed by value". Seems pass dynamically allocated array to function and delete array inside the function is not a good idea. nullptr does not work, so delete[]. Is it correct. Please share your thoughts.

    • Alex

      You should use delete if tempPtr is a pointer to a single object, and delete[] if tempPtr is a pointer to a dynamically allocated array.

      • AMG

        Yes, I got it, but nor sure if delete[] works in above example (int *tempPtr is a pointer to dynamically allocated array). As you said, tmpPntr = nullptr won't change tmpPtr outside setToNull(). Because of that, I think delete[] doesn't work. Thanks.

      • AMG

        Alex, never mind. I wrote code and understood. Found answers for my questions. Frankly speaking, I should have written a code before ask you for help. Sorry about that.

  • nikos-13

    When nullptr is a valid argument?

    • Alex

      A nullptr is a valid argument for any pointer parameter.

      • nikos-13

        Oh, so what do you mean with "When passing pointer values and nullptr is not a valid argument"? Can you give me an example?

        • Alex

          nullptr is always a valid argument for a pointer parameter from a syntax perspective, but it may not be from a logical perspective. For example, consider the following function:

          Although you could pass a nullptr for the array parameter, logically it doesn't make any sense to, and it will cause a null dereference, which will crash your program. This is what I mean by "not a valid argument".

          Now, when passing a fixed array, it still makes sense to pass it by address, so this is really pertaining to pointers to non-array values.

  • nikos-13

    "In the lesson on passing arguments by reference, we briefly mentioned that references are typically implemented by the compiler as pointers."

    We mentioned that at lesson 6.11 -- Referende variables ( ), not on the previous lesson.

  • justin

    At the beginning you say "Pass by address is typically used with pointers, which most often are used to point to built-in arrays or dynamically allocated variables." but dynamically allocated variables are assigned to pointers them selves, were passing an address by reference would be the right way to do that I would think. Or maybe by that you were saying that pass by address is often used as a method to assign a pointer a dynamically allocated variable by passing the memory request (new int) as an argument to a pointer declared as a parameter in a function deceleration like this

    • justin

      sorry meant to say "void foo(*ptr)" not "void foo(*point)".

    • justin

      My bad I reread it and understand it now. you can delete my question if you wish. Its not reverent.

    • Alex

      It depends on whether nullptr is a valid option or not. If nullptr is a valid argument to your function, then pass by address is better than pass by reference. If nullptr is not a valid argument to your function, then I agree pass by reference is safer.

  • Mr C++

    Don't You Think It should be like this because when i do this it prints nothing(returns void) which was intended...And, When i do it through your prog. it prints 0 0 0 0 0 0(which i think would not be intended by the programmer) we passed a null array so it should return nothing rather than printing 0 0 0 0 0.....??

    Tell Me If I'm Right !!

    • Alex

      Your array isn't a null array, it's a 6-element array with each element initialized to 0.

      You clearly didn't test this code. Try passing in a nullptr (or 0) for the array parameter and see what happens.

      • Mr C++

        Oh ! I thought U were talking about what if all elements of array are set to NULL then what happens so in that case my program works right and returns nothing instead of printing 0's but Yes, I Know Dereferencing a nullptr causes undefined behaviour....

        • dražen

          I don't think you fully understand difference between NULL array and array with elements initialized to 0. array itself when declared cannot be NULL. you can have pointer to array which is NULL. array elements can be NULL, but only if array elements are pointers, and your array is of type int.

  • Drew

    Hi Alex!

    I believe I understand the point you're making here, but I think it's a bit confusing:

    "Therefore, we can conclude that C++ really passes everything by value! The properties of pass by address (and reference) comes solely from the fact that we can dereference the passed address to change the argument, which we can not do with a normal value parameter!"

    But, you've mentioned numerous times up to this point that passing large classes/structs by value can be very expensive because it copies those variables into the function parameters every time you call the function. So in fact there is a difference between passing by value and passing by reference, right?

    • Alex

      Yes, there is a difference!

      In the case of pass by value, the entire argument is copied into the parameter, which can be slow if the argument is large.
      In the case of pass by address, the address that the argument pointer is holding is copied. This is fast because an address is only 32 or 64 bits.
      In the case of pass by reference, the reference is passed (which is usually an address as well). This is also fast.

      So regardless of whether you pass by value, address, or reference, C++ is copying the argument to the parameter. However, the size of what is copied can vary significantly depending on the technique used.

  • J

    Question if you make a ref to a pointer and pass in a class do you still use -> to access the class members Im wondering because i f I create a dynamic object with new I have to use a pointer but dont really want to dereference the pointer everytime

  • boddooo

    Hi sir, This is a great work thank you
    my question
    you said when not to pass by address in passing structs or classes but I see in many great libraries like Assimp and many others they pass structs by address.

    • Alex

      I presume these libraries are either C libraries, or were ported from C. C doesn't have references, which are superior for most kinds of parameter passing. So if you want a library to be compatible with both C and C++, you're stuck passing by address.

  • simone

    Hi, Alex. I was trying to buils a simple function that takes a numeric array as input and returns the address of a struct representing a pile with the array values "piled up". However, something does not work.

    This returns the output: 3 (which is fine) and then other two strange numbers.

    I thought that the problem could be that the data pile->next is destroyed, as well as all the other nexts. I also tried to allocate in the main

    before calling the function. In this way, it works. But I was wondering whether there was a way to make it work without doing anything outside the simple_function.

    Can you help me?


  • Xoce

    Hi Mr Alex,
    can we pass an array to a function by value since an array is implicitly converted to a pointer to its first element. which means that an array must be passed by address or reference to a function like for example: func(int &array) or func(int* array) or func(int array[]), am i right? thank you.

    • Alex

      No, you can't pass a C-style array by value (in a way that will cause the entire array to be copied). You can pass it by address. There is a way to pass them by reference but not as you suggest (func(int &array) won't work).

  • Ninja

    So I tried to use pointer arithmetic to print the array but it is displaying 6 6 6 6 6 6 instead of 1 2 3 4 5 6.
    I'm following the same logic you used in lesson 6.8a (pointer arithmetic and array indexing) for the C-style string array but its not working here.
    Here is my code below

    • Alex

      Your printArray() loop is printing the value *array, which always points to the first element of the array and never gets incremented.

      You probably meant to print *i, not *array.

      • Ninja

        Oh silly me lol. Makes sense thx. Also I noticed the compiler won't let me make the *array constant (const int *array) when I use pointer arithmetic. I was wondering why I can't make it constant since I'm not changing *array?

        • Alex

          (comment removed to avoid confusion)

          • Ninja

            I'm confused, wasn't it the other way around the whole time? That if you put const before the type, then it is a pointer to a constant value and if const is between type and variable, then its a constant pointer to a non-constant value. I feel like this code does the opposite of everything I learned (about constants)

            • Alex

              Yes, you're right. Sorry, I totally screwed that up.

              I think the actual issue here is that when you have const int *array (which is a pointer to an array of const ints), you can't assign int *i to point to it (because i is non-const). You'd have to make i point to a const int as well for this to work (const int *i = array).

Leave a Comment

Put all code inside code tags: [code]your code here[/code]