7.2 — Passing arguments by value

Pass by value

By default, non-pointer arguments in C++ are passed by value. When an argument is passed by value, the argument’s value is copied into the value of the corresponding function parameter.

Consider the following snippet:

In the first call to foo(), the argument is the literal 5. When foo() is called, variable y is created, and the value of 5 is copied into y. Variable y is then destroyed when foo() ends.

In the second call to foo(), the argument is the variable x. x is evaluated to produce the value 6. When foo() is called for the second time, variable y is created again, and the value of 6 is copied into y. Variable y is then destroyed when foo() ends.

In the third call to foo(), the argument is the expression x+1. x+1 is evaluated to produce the value 7, which is passed to variable y. Variable y is once again destroyed when foo() ends.

Thus, this program prints:

y = 5
y = 6
y = 7

Because a copy of the argument is passed to the function, the original argument can not be modified by the function. This is shown in the following example:

This snippet outputs:

x = 5
y = 5
y = 6
x = 5

At the start of main, x is 5. When foo() is called, the value of x (5) is passed to foo’s parameter y. Inside foo(), y is assigned the value of 6, and then destroyed. The value of x is unchanged, even though y was changed.

Function parameters passed by value can also be made const. This will enlist the compiler’s help in ensuring the function doesn’t try to change the parameter’s value.

Pros and cons of pass by value

Advantages of passing by value:

  • Arguments passed by value can be variables (e.g. x), literals (e.g. 6), expressions (e.g. x+1), structs & classes, and enumerators. In other words, just about anything.
  • Arguments are never changed by the function being called, which prevents side effects.

Disadvantages of passing by value:

  • Copying structs and classes can incur a significant performance penalty, especially if the function is called many times.

When to use pass by value:

  • When passing fundamental data type and enumerators, and the function does not need to change the argument.

When not to use pass by value:

  • When passing structs or classes (including std::array, std::vector, and std::string).

In most cases, pass by value is the best way to accept parameters of fundamental types when the function does not need to change the argument. Pass by value is flexible and safe, and in the case of fundamental types, efficient.

7.3 -- Passing arguments by reference
7.1 -- Function parameters and arguments

31 comments to 7.2 — Passing arguments by value

  • DJ Koze

    You told us above not to pass arrays by value because of performance issues.
    But is it possible to pass an array by value?
    I mean it does decay into a pointer anyways.

    • Alex

      Not, it's not possible to pass a fixed array by value (as you note, if you try it will decay into a pointer). However, you can pass a std::array by value.

      • The "arrays" in "When passing arrays, structs, or classes" is redundant then, since @std::array is a class. I think this wording might add to the confusion of some readers who mix up C-style arrays with @std::array.

        • Alex

          I'm not sure I agree -- you shouldn't use pass by value when you're passing arrays (either fixed arrays or std::array). The fact that you _can't_ do so for fixed arrays doesn't make the statement any less true. 🙂 Thoughts?

          • @std::array is excluded by my previous comment, @std::array and C-style arrays should be differentiated to avoid confusion.
            Saying "you shouldn't" about something that's just not possible is pointless in my opinion. Imagine reading "You shouldn't change your phone's tires while it's turned on" in a manual, that's equally meaningless.
            You probably mentioned that arrays can't be passed by value in the relevant lesson(s), removing the need of explicitly mentioning them here.

  • DecSco

    You wrote that pass by value is efficient for fundamental data types. Is that more due to pointer size or the additional dereferencing step?
    I mean, on a 32-bit system, a pointer is 4 bytes, but a long long is four times that. Does it still apply then? Or would I have to test it if that case is ever relevant?

    • nascardriver

      Hi DecSco!

      > Is that more due to pointer size or the additional dereferencing step?
      The dereferencing step.

      > a pointer is 4 bytes, but a long long is four times that.
      "There are five standard signed integer types : “signed char”, “short int”, “int”, “long int”, and “long
      long int”. In this list, each type provides at least as much storage as those preceding it in the list."
      - C++ ISO N4727 § 6.7.1
      The size of a long long could be 1 byte if the compiler developers wanted to, usually a long long uses 8 bytes.

      > Does it still apply then?
      Your computer has is good at handling 1, 2, 4, 8 bytes on 32bit plus 16 bytes on 64bit. Anything larger will take extra effort and extra time. I don't know if dereferencing is faster or slower than passing 16 bytes by value on a 32bit system, I'd pass by value.

      > if that case is ever relevant?
      The difference is so minimal you probably won't even be able to measure it, feel free to try it though. If you decide to measure it, make sure to disable compiler optimizations, because your compiler will probably produce the same output for both methods, picking the one it thinks is faster.

      If you have anything that's not of standard size, pass it be reference or pointer.

  • Peter Baum

    The first sentence of this lesson is false.  By default, arrays are not passed by value as the following code demonstrates:

    In other words, the values of the array are not copied for the call because if they were, the values of the original array would not change.

    • nascardriver

      Hi Peter!

      The value of an array aren't the element values, an array's value is a pointer to the first element. This gets more obvious when you use the pointer syntax for arrays (Don't do this though, arrays should use square brackets)

      • Peter Baum

        Hi nascardriver,

        Thanks again for all your work in the comment section.  You are an important element of the success of this site.

        Regarding what it means to pass something by value.  As Alex explains in a later lesson, we can view the passing of arguments as always, in some sense, just passing "everything" by value.  The idea is that we always pass a value of something, whether it is a pointer, and address, or whatever.  We can, of course, view thing this way.  However, the problem with doing this is that we use terms like "by value", "by address", and "by reference" to try to communicate something more about what is being passed, how it might be used, and other consequences.  The only way to make all this clear is to be certain the terms are used consistently, and preferably, giving specific definitions of these terms.  If this is not done, some students are going to be confused.

        Although I don't remember a specific definition of "by value" given in the lessons, from the examples I interpreted it to mean that the whole object would be copied.  Thus, for an array, all the elements as well as any length information available would be copied.

        Again, as a minimum, I think this should be a flag that some students (or at least one) is confused by what has been written and perhaps should be examined to make things more clear.

    • Alex

      I've amended the text to note that pass by value is the default for non-pointer arguments. Thanks for pointing out the misleading wording.

  • John Kennedy

    I think you should make your code more accurate, you lost #include <iostream>

  • great, you are the best mr alex

  • Joe Dunleavy

    Hi Alex, thanks a ton for taking the time and making C++ free and easy to access for anyone in the world. In fact, I like your tutorial series so much and I'm having so much fun I was wondering if you had any more websites or content that is similar to yours? Thanks again. Best regards, Joe.

  • Felipe

    I think you forgot to remind that, arrays passed as arguments can be modified.

  • Nyap

    wow this is easy compared to last chapter
    the lessons feel so short 😀

  • Me

  • Nver

    this can cause a performance penalty, especially if the function is called many times.            /////I didn't understand what did you mean

    • Alex

      Every time you call a function with a value parameter, the parameter has to be copied. This can be expensive in terms of time or memory or both. If that same function is called 1,000 times, the value parameter will be copied 1,000 times (once for each call).

  • FakeEngineer

    Great tutorial,i think i will make a good programmer out of this.

  • som shekhar

    can enum be passed as parameter through this method(pass by value)?

Leave a Comment

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