7.3 — Passing arguments by reference

While pass by value is suitable in many cases, it has a couple of limitations. First, when passing a large struct or class to a function, pass by value will make a copy of the argument into the function parameter. In many cases, this is a needless performance hit, as the original argument would have sufficed. Second, when passing arguments by value, the only way to return a value back to the caller is via the function’s return value. While this is often suitable, there are cases where it would be more clear and efficient to have the function modify the argument passed in. Pass by reference solves both of these issues.

Pass by reference

To pass a variable by reference, we simply declare the function parameters as references rather than as normal variables:

When the function is called, ref will become a reference to the argument. Since a reference to a variable is treated exactly the same as the variable itself, any changes made to the reference are passed through to the argument!

The following example shows this in action:

This program is the same as the one we used for the pass by value example, except foo’s parameter is now a reference instead of a normal variable. When we call addOne(value), ref becomes a reference to main’s value variable. This snippet produces the output:

value = 5
value = 6

As you can see, the function changed the value of the argument from 5 to 6!

Returning multiple values via out parameters

Sometimes we need a function to return multiple values. However, functions can only have one return value. One way to return multiple values is using reference parameters:

This function takes one parameter (by value) as input, and “returns” two parameters (by reference) as output. Parameters that are only used for returning values back to the caller are called out parameters. We’ve named these out parameters with the suffix “out” to denote that they’re out parameters. This helps remind the caller that the initial value passed to these parameters doesn’t matter, and that we should expect them to be rewritten. By convention, output parameters are typically the rightmost parameters.

Let’s explore how this works in more detail. First, the main function creates local variables sin and cos. Those are passed into function getSinCos() by reference (rather than by value). This means function getSinCos() has access to the actual sin and cos variables, not just copies. getSinCos() accordingly assigns new values to sin and cos (through references sinOut and cosOut respectively), which overwrites the old values in sin and cos. Main then prints these updated values.

If sin and cos had been passed by value instead of reference, getSinCos() would have changed copies of sin and cos, leading to any changes being discarded at the end of the function. But because sin and cos were passed by reference, any changes made to sin or cos (through the references) are persisted beyond the function. We can therefore use this mechanism to return values back to the caller.

This method, while functional, has a few minor downsides. First, the caller must pass in arguments to hold the updated outputs even if it doesn’t intend to use them. More importantly, the syntax is a bit unnatural, with both the input and output parameters being put together in the function call. It’s not obvious from the caller’s end that sin and cos are out parameters and will be changed. This is probably the most dangerous part of this method (as it can lead to mistakes being made). Some programmers and companies feel this is a big enough problem to advise avoiding output parameters altogether, or using pass by address for out parameters instead (which has a clearer syntax indicating whether a parameter is modifiable or not).

Personally, we recommend avoiding out parameters altogether if possible. If you do use them, naming out parameters (and output arguments) with an “out” suffix (or prefix) can help make it clear that the value might be modified.

Limitations of pass by reference

Non-const references can only reference non-const l-values (e.g. non-const variables), so a reference parameter cannot accept an argument that is a const l-value or an r-value (e.g. literals and the results of expressions).

Pass by const reference

As mentioned in the introduction, one of the major disadvantages of pass by value is that all arguments passed by value are copied into the function parameters. When the arguments are large structs or classes, this can take a lot of time. References provide a way to avoid this penalty. When an argument is passed by reference, a reference is created to the actual argument (which takes minimal time) and no copying of values takes place. This allows us to pass large structs and classes with a minimum performance penalty.

However, this also opens us up to potential trouble. References allow the function to change the value of the argument, which is undesirable when we want an argument be read-only. If we know that a function should not change the value of an argument, but don’t want to pass by value, the best solution is to pass by const reference.

You already know that a const reference is a reference that does not allow the variable being referenced to be changed through the reference. Consequently, if we use a const reference as a parameter, we guarantee to the caller that the function will not change the argument!

The following function will produce a compiler error:

Using const is useful for several reasons:

  • It enlists the compilers help in ensuring values that shouldn’t be changed aren’t changed (the compiler will throw an error if you try, like in the above example).
  • It tells the programmer that the function won’t change the value of the argument. This can help with debugging.
  • You can’t pass a const argument to a non-const reference parameter. Using const parameters ensures you can pass both non-const and const arguments to the function.
  • Const references can accept any type of argument, including non-const l-values, const l-values, and r-values.


When passing an argument by reference, always use a const reference unless you need to change the value of the argument.

A reminder

Non-const references cannot bind to r-values. A function with a non-const reference parameter cannot be called with literals or temporaries.

References to pointers

It’s possible to pass a pointer by reference, and have the function change the address of the pointer entirely:

(We’ll show another example of this in the next lesson)

As a reminder, you can pass a C-style array by reference. This is useful if you need the ability for the function to change the array (e.g. for a sort function) or you need access to the array’s type information of a fixed array (to do sizeof() or a for-each loop). However, note that in order for this to work, you explicitly need to define the array size in the parameter:

This means this only works with fixed arrays of one particular length. If you want this to work with fixed arrays of any length, you can make the array length a template parameter (see chapter 13).

Pros and cons of pass by reference

Advantages of passing by reference:

  • References allow a function to change the value of the argument, which is sometimes useful. Otherwise, const references can be used to guarantee the function won’t change the argument.
  • Because a copy of the argument is not made, pass by reference is fast, even when used with large structs or classes.
  • References can be used to return multiple values from a function (via out parameters).
  • References must be initialized, so there’s no worry about null values.

Disadvantages of passing by reference:

  • Because a non-const reference cannot be initialized with a const l-value or an r-value (e.g. a literal or an expression), arguments to non-const reference parameters must be normal variables.
  • It can be hard to tell whether an argument passed by non-const reference is meant to be input, output, or both. Judicious use of const and a naming suffix for out variables can help.
  • It’s impossible to tell from the function call whether the argument may change. An argument passed by value and passed by reference looks the same. We can only tell whether an argument is passed by value or reference by looking at the function declaration. This can lead to situations where the programmer does not realize a function will change the value of the argument.

When to use pass by reference:

  • When passing structs or classes (use const if read-only).
  • When you need the function to modify an argument.
  • When you need access to the type information of a fixed array.

When not to use pass by reference:

  • When passing fundamental types that don’t need to be modified (use pass by value).

Rule: Use pass by (const) reference instead of pass by value for structs and classes and other expensive-to-copy types.

7.4 -- Passing arguments by address
7.2 -- Passing arguments by value

155 comments to 7.3 — Passing arguments by reference

  • wdbhckng

    >As a reminder, you can pass a C-style array by address by reference.

    I don't think I quite get it. If the array never decays to a pointer, how is it passing by address by reference and not just passing by reference?

  • giang

    So, reference parameter's still be destroyed if it goes out of its fuction scope, right???

    • nascardriver

      The reference gets destroyed, but not the object that was referenced.

  • Jojo

    I have a question about the terms "non const l-values", "const l-values" and "r-values": do non const l-values include exactly non const variables; const l-values literals and const variables; r-values results of expressions?
    Moreover, in the sentence "Const references can accept any type of argument, including l-values, const l-values, and r-values. ", did you mean "Const references can accept any type of argument, including non const l-values, const l-values, and r-values." instead?

    • nascardriver

      Value categories deserve a lesson on their own and are too big to be explained in a comment. Please see the page on cppreference. If you have questions to something in specific, please ask.

      > Moreover, in the sentence [...]
      Yep, lesson amended, thanks!

      • Jojo

        Hi nascardriver,
        Thanks for your answer, indeed by looking at the page, I see l- and r- values include more values than I thought!
        > Yep, lesson amended, thanks!
        No problem! :)

  • chai

    As mentioned above
    "Personally, we recommend avoiding out parameters altogether if possible. If you do use them, naming out parameters (and output arguments) with an “out” suffix (or prefix) can help make it clear that the value might be modified."
    Will it better to use pointers instead?

    • nascardriver

      Syntax-wise, yes absolutely. It's immediately obvious at the call-site that the argument will be modified.

      The problem with pointers for out parameters is that you could pass a `nullptr`, potentially breaking the function you're calling. That can't happen with references.
      To disallow `nullptr` to be passed, you can use `not_null` from the guidelines support library

  • Sriram M R

    In the above the output we get upon debugging is
    The sin is 0.5
    The cos is 0.866025

    I calculated using a calculator the radians value comes down to 0.52359877559829887307666666666667

    Then why is sin output is just 0.5 ? and not 0.523.....
    Why is cos value 0.866025 ?
    sin and cos both have been initialized as 0.0
    As they both are copy the value of radians
    How did 0.866025 get copied instead of 0.5?

  • Connor

    Would you advise using the Microsoft SAL annotations, such as _In_, _Out_, etc. for annotating whether a parameter is an input or output? Thanks.

    • Alex

      I personally would not -- I find it redundant to denote "in" parameters with an "in" prefix, since it's reasonable to assume parameters are "in" unless otherwise noted. "Out" parameters are the odd case, and the ones that should be annotated somehow.

      As an aside, it's also not recommended to start variable names with an underscore in C++.

  • Mark Smith

    "with an “out” prefix can help make it clear" - I think you mean "suffix"?

    Kind regards

  • Parsa

    What do you mean by mixing the input and output parameters?

    Also, even if you don't pass the pointer by reference, wouldn't it still be pointing to the same address as the argument therefore it can be changed anyway?

  • Nathan

    Insted of passing around a struct by refrence or pointer, is it acceptable to use a namespace and modify/read them in the program when needed?

  • Only if you need those instances very often. This approach is not a replacement for parameters.

  • NooneAtAll

    What's the difference between



    One is const value, can't be modified, accepts anything
    Other is const reference, can't be modified, accepts anything

    What's the disadvantage of always using second one?
    The only situation with difference I can think of is multithreading causing the original to be modified, but are there others?

    Edit: Can't embed..

    • It's possibly slower for built-in types (int, float, etc.), because there has to be an indirection.
      If @foo wants to modify @A, it needs another variable.

      • daniel

        correct me if im wrong but i think you shouldnt be using an const pass by reference anyways if you needed to modify the parameter...

    • Marco

      The first one will make an internal copy of the parameter you pass, the second one not. This means that in the first case it is an extra 4 byte in RAM occupied in a useless way and for very big programs that may add up quickly.
      Creating the variable is also slower than just passing the address and the compiler will already make sure of the consistency for not changing the const &.

      If needed one can change the value of a constant variable using a pointer to that variable address. This may be done in the first case, not sure about the second one.

      • The first one occupies `sizeof(int)` (probably 4) bytes, the second one `sizeof(void*)` (probably 8) bytes. Additionally, the second version has to deal with indirection. Arguments aren't passed through RAM, that would be terribly slow, they stay on the CPU.
        Fundamental types should be passed by value.

        > If needed one can change the value of a constant variable using a pointer to that variable address
        That's undefined behavior.

        • Anastasia

          But how would it know that the value stored at the address we are writing to is supposed to be const if we were to access it via a non-const pointer (by "non-const" I mean pointer-pointing-to-a-non-const-value)?

          And I hate pointing it out, but in the examples above 'void' functions are returning ints...

          • I don't understand, can you elaborate or give an example?

            > in the examples above 'void' functions are returning ints
            Thanks, it's too late to edit it :(

            • Anastasia

              I know, you'll say that the result is undefined, but still how would it know that the value at that (marked as const) address is not supposed to be written to, if the pointer accessing it doesn't indicate that?

              • It doesn't know that the value isn't supposed to be written to.
                It's UB, so I can't say a lot more. It will probably try to write anyway and you'll get an access violation (If the target isn't writable).

                • Anastasia

                  Oh, I thought maybe it was indicated somehow by particular bits arrangement or something like that... It's still unclear to me why it's not allowed then (or should I say why it's allowed in the first place?). We can get access violation writing to an array anyway (c-style ones don't do any bound checking) so it's unsafe either way.

                  • It'd be nice if there was no need for `const_cast`, because as you noticed, it can cause trouble.
                    Bjarne Stroustrup wrote a paper about the then-new casts in which he shows some examples in which `const_cast` is required ( Page 14+, Appendix A). The examples use classes, templates and function overloading. If you're not that far yet, you might not understand them.

                    Objects should be allowed to modify their internal state (That's not visible to the outside). Without `const_cast`, `const` objects aren't allowed to modify themselves, even if the caller would be unaffected. Bjarne talks about a "never const" qualifier. That doesn't make sense to me, because that's what `mutable` does.
                    Basically, we allow functions to modify their local variables, so classes should be allowed to modify their "local" variables.

                    When you're overloading member functions that differ in constness of their return type, you don't want to duplicate a function for the sole sake of marking one as `const`. With `const_cast`, you can write a `const` version and let the non-const version `const_cast` `this` to non-const and call the non-const overload (Assuming the non-const overload is not modifying the object).

                    There's also an example about shared representations, but I don't understand it.

                    EDIT: That paper is from 1992, `mutable` might not have been available then.

                    • Anastasia

                      Wow, that really looks interesting, I'll read it (hopefully I'll be able to understand at least something, if not I'll come back here to ask dumb questions again :D (I'll try not to, I promise)). Thanks a lot for sharing and for the explanation, much appreciated!

  • Nguyen


    When an argument is passed by value, the argument’s value is copied into the value of the corresponding function parameter.  This means an argument must have a value to pass to the function parameter.


    Looks like to me, an argument does not need to be initialized/assigned with a value when an argument is passed by reference?


    • > This means an argument must have a value to pass to the function parameter.
      Every variable has a value. @x has an indeterminate value.
      Both of your programs compile. The former causes a warning, you may have told your compiler to treat warnings as errors. This is a good setting.

  • Behzad

    What is the actual mechanism behind passing an expression argument (e.g. i+1) through a constant reference?
    I think it should be similar to passing by value.

    • The expression is evaluated and the result is stored in a temporary. The reference references this temporary.

  • NXPY123

    I just realized passing by reference and repeated function calling together can help print 1 to 100

  • darshan

    Is there a difference between


    because second one is more intuitive compared to first one (for passing pointer by reference).

  • Nguyen

    Hi Alex,

    There are two examples in the previous lesson.   In both examples, you mentioned the variable Y is destroyed when foo() ends.  But I don’t see it mentioned in this lesson.  I assume it is destroyed when the functions end.  If the reference is destroyed when the called function ends, then how could the argument still remember/know its value had been changed in the called function?


    • Alex

      Yes, reference parameters are destroyed at the end of the function.

      A reference parameter is just an alias to the argument -- so when we use a reference parameter to change a value, we're actually changing the value of the argument. If the reference is later destroyed, it doesn't matter, because the argument still exists.

      In other words, the reference is useful as long as it is alive, but its destruction does not affect the argument.

  • ............

    I understand the second one but I am confused in the first. Can you please explain this again. And according to my memory i think alex never mentioned the first one. I saw that only in this lesson.

    • The first changes the address stored in @ptr. Since @ptr is a copy of @main::ptr, this doesn't affect @main::ptr.
      The second changes the value pointed to by @ptr. @ptr and @main::ptr point to the same value, so this change affects @a.

    • Dave

      In the first example you create b on the stack and assign the copied ptr to point at the stack address.
      When the function ends, both b and the copy of ptr are removed from the stack so your work is discarded.
      Note that you can get into trouble if you modify a referenced pointer to point at a temporary (stack) variable:
      void foo(int &ptr){
      int b = 8; // stack variable
      ptr = &b; // address of b on stack
      This may compile, but the result is that the pointer passed intk the function will contain a stack address and will be quickly reused for something else.

  • Clapfish

    Hi Alex! I hope you're well.

    Some amendment suggestions:

    1) In the "Pass by reference" section, the second cope snippet is inconsistent with the first and third. It contains the variable 'value' and reference '&value', and the text immediately afterwards talks about 'x' and '&y' thus: "When we call foo(x), y becomes a reference to x." Also, 'cout' usage instead of 'std::cout'.

    2) Just above the "Limitations of pass by reference" section, in the large paragraph, the following sentence might be inconsistent:

    "Second, the caller must pass in variables to hold the updated values, which means it must have (or create) parameters to hold these output values even if it doesn’t intend to use them."

    Shouldn't it say something like:

    "Second, the caller must pass in arguments designed to hold the output values, which means it must have (or create) variables to hold the updated values even if it doesn't intend to use them."

    (Hopefully I'm not getting my terminology mixed up here - please correct me if I am!)

    3) Just above the "References to pointers" section:

    "Rule: When passing an argument by reference, always use a const references unless you need to change the value of the argument"

    Should be: '...always use a const reference...' (-s)

    4) Under "Disadvantages of passing by reference:"

    "Because a non-const reference cannot be initialized with an const l-value or an r-value (e.g. a literal or an expression), arguments to reference parameters must be normal variables."

    '...a const l-value...' (not an)
    '...arguments to non-const reference parameters...' (specifically)

    "It can be hard to tell whether a parameter passed by non-const reference is meant to be input, output, or both. Judicious use of const and a naming suffix for out variables can help."

    '...a non-const reference parameter is meant for...' (suggestion, since [as I understand it] arguments are passed, not parameters)

  • DecSco

    "As a reminder, you can pass a C-style array by pointer by reference." Is the "by pointer" erroneously placed there?

  • Peter Baum

    1. In the section “Returning multiple values via out parameters” the use of “sin” and “cos” as simple variables is problematic.
       a. They have the same name as the common trigonometry functions, especially if a using statement is used.
       b. Initialization such as

    looks very much like a function call.

    One does see this kind of thing when reading code, so I think it is great to point out this potential for confusion.  However, as a code example, maybe using other names would be a better choice.

    2. In the section “Pros and cons of pass by reference”, I didn’t understand the statement:

    • References must be initialized, so there’s no worry about null values.

    The following example demonstrates that the statement is false.  The reference is assigned a value but not initialized within the function.  Also the argument is not initialized before the call.

    Perhaps the intent was to say something about functions using a reference parameter to give the argument a value, and in such a case, the argument does not have to be initialized.

    3. The sentence
    “Because a non-const reference cannot be made to an const l-value or an r-value (e.g. a literal or an expression), reference arguments must be normal variables.”

    is confusing because the word reference can be a noun or transitive verb.  Look in particular at the first use of the word.  I think what is meant is that the argument of a function cannot be a const l-value or an r-value if the corresponding parameter of the function is a non-const reference.

    • nascardriver

      Hi Peter!

      1. I pointed this out too, but I can't find my comment. Alex' response was something along the lines
      "These variables have fitting names, because they store sin and cos, you can still access the functions by using ::sin and ::cos".
      Generally, @std::sin and @std::cos should be used. 'using namespace' should be avoided and uniform initialization should be used, because direct initialization can be mixed up with function calls.

      2. @x is initialized to @xx, not the value of @xx! There are no uninitialized references (Unless you're using a reference wrapper).

      • Peter Baum

        Hi nascardriver,
        Regarding item 2.  You could certainly view &x as an initialization or the assignment as an initialization, but that doesn't seem to fit within any of the examples given of initialization and there is no definition of initialization given in the lessons that would suggest this interpretation.  In any event, I think, as a minimum, it shows a place where students might get confused and so a little more work is needed.

        • Alex

          Regarding item 2, The initialization of reference x happens when the function call is made, and reference parameter x is initialized with argument xx. xx isn't a null value, it's an undefined value. When I said, "null value", I generally meant 0/NULL/nullptr.

          Regarding item 3, I've reworded the sentence as: "Because a non-const reference cannot be initialized with an const l-value or an r-value (e.g. a literal or an expression), arguments to reference parameters must be normal variables."

          Hopefully that is more clear. Thanks for pointing out the confusing wording.

          • Peter Baum

            Hi Alex,

            Item 3 looks good.

            Now I'm even more confused about 2.  I think some definitions would help.  How can reference parameter x be initialized with argument xx if xx is an undefined value?  The only thing the run-time system could do is initialize it to some "null value." But why would it bother to do that?

            • nascardriver

              @x isn't initialized to the value of @xx, it's initialized to the address of @xx. Imagine references like pointers with a different syntax, because that's pretty much what they are.

              • Peter Baum

                I follow what you are saying, but don't forget, Alex said "it's an undefined value", so at that point he couldn't be talking about the address of @xx because that address is known.  Maybe he meant something else by "it."  I think at this point the problem is really English rather than computer language.

                Thanks for wading in though... it helps.

                • nascardriver

                  "it" is the value of @xx. The value of @xx is undefined.

                • Peter Baum

                  At this point we have to go back to the original statement:

                  "References must be initialized, so there’s no worry about null values."

                  Now I agree with Alex (and nascardriver) that, to use "initialization" broadly, we can say, as Alex wrote:

                  "The initialization of reference x happens when the function call is made, and reference parameter x is initialized with argument xx."

                  provided, as nascardriver suggests, we are talking about addresses rather than values.  If the addresses are the same, the values will also be the same.

                  But, in the first sentence above, the words "must be" were used.  To me that is different from something that happens automatically.  I interpret it to be summarizing what the programmer needs to do.

                  At this point, I think Alex should just rewrite it to says whatever he intends.  Since, although I agree with what nascardriver is saying, I don't know what Alex meant to say.

                • Alex

                  We hit the max thread depth, so replying here to your last comment.

                  I say "must be" because the programmer must provide an initializer for the reference. That does not happen automatically.

                  In the case where a reference is declared as a local variable, the initializer must be supplied as part of definition:

                  In the case of a function reference parameter, the parameter's initializer is the argument that is passed in when the function is called (which the programmer provides).

                  I'm still not totally clear on where the disconnect between what I'm saying and what you're understanding is, but I'd love to clarify further.

                • Peter Baum

                  That helps a lot Alex.  When the  phrase "initialization" is used, the only other thing that might make things more understandable is to make sure it is clear when the initialization occurs - at compile time or at run-time.

                • Alex

                  References can be initialized at either compiler or run-time, depending on what they are referencing.

                  But obviously a reference parameter can't be initialized until run-time.

                  These follow the same logic as initialization of normal variables, so I'm not sure a specific callout is warranted.

  • waz

    hi Alex - great tutorial!!
    I am trying to pass a pointer by reference ... I change the value of the pointer within the function and then from the caller can see the new value. However when dereferencing the pointer from the caller I get junk ... not sure where I am going wrong - please help..

    using namespace std;
    void printVal(int *&ptr1) {    
        int y = 15;
        ptr1 = &y;
        cout << "In function: " << ptr1 << endl;
        cout << "In function: " << *ptr1 << endl;

    int main()  {
        int x = 5;
        int *ptr = &x;
        cout << ptr << endl;
        cout << *ptr << endl;
        cout << "After function: " << ptr << endl;
        cout << *ptr << endl;
    // output as follows:-
    In function: 0x7fff5fbff5e4
    In function: 15
    After function: 0x7fff5fbff5e4
    32767     // this should be 15 ???

    • nascardriver

      Hi waz!

      You have a dangling pointer. Declare @y static or outside of @printVal.

  • Cosmin

    Why it is not a good idea to pass by reference a built-in array? Also, by built-in array you mean something like:

    Am I correct?

    • nascardriver

      Hi Cosmin!

      The only reason I can think of is that you have to explicitly state the size of the array in the function declaration. This causes your function to only be able to accept arrays of one specific size. When passing an array by address you can have another parameters to pass the size to allow your function to handle all sizes of arrays.

    • Alex

      It's fine to pass a built-in array by address by reference if you want the function to be able to modify the array or use sizeof(). I'll make this clearer.

  • The Inquisitive Dude

    Sir, in the following code:

    When I put '&' before withdrawMoney and depositMoney arguments in the methods withdraw and deposit respectively, it throws an error, but it works for money in balance. Why?

    • nascardriver

      Yo Dude!

      The error is caused by you passing r-values to those functions, you cannot have a standard reference to an r-value. If you modified your @main function like so

      it'd work.

      This isn't nice though, that's why you shouldn't pass a simple reference to those functions but a const reference instead.

      Also, don't use 'using namespace x;'

  • Paul

    I am a little confused. sin and cos in  getSinCos are C++ built-in functions, right?   But sin and cos in main function are variables?

    • nascardriver

      Hi Paul!

      You're correct. The variable names are badly chosen, after declaring them you won't be able to use the sin and cos functions in main.

      • Alex

        I'm not sure I'd say the variable names are badly chosen -- they reflect exactly what those things are meant to be. You can still use the C-style sin and cos functions in main by prefixing them with the :: scope resolution operator, to indicate that you want to use the global function, not the local variable.

        That said, we really should be using the standard library version of these functions since this is C++. I've updated the example accordingly.

  • Rasikko

    I've read that you should only pass a struct/class to a function by reference. Does this apply to their member variables/functions as well?

    • nascardriver

      Hi Rasikko!

      To answer your question you'll need a little bit of background knowledge.
      Your computer is good at handling data types with a size of 2^n bits. That is 1, 2, 4, 8, 16, 32, 64 and so on. It stops being good at types larger than 32 bits on x86 or 64 bits on x64 systems.
      Structs and classes are usually larger that 32 or 64 bits or they have an odd size, thus making your program run slower than it could be. On top of that you'll create a copy of the object every time you pass it to a function without passing it by reference (copying memory is slow).
      By passing a reference you're not creating a copy, instead you're only passing the address of the object you want to pass. That address is exactly 32 or 64 bits in size, making it great for your computer to work with.

      If your member variable has an odd size you should pass it by reference.
      All the standard numeric types (char, int, long, float, double, ...) can be passed by value, because they have 2^n sizes. Anything other than those should be passed by
      (const) reference.

      • Rasikko

        Ok, I think I understand. My machine is 64bit. So it appears it's ok to pass by value(they are all numeric types) and to pass by reference if it's other types or the whole class/struct. Thank you for your answer. I was stuck on that for sometime.

  • Aitor

    Hi Alex,
    i'm trying to understand, why "const int& variableName" as a function parameter works with constant literals, it is a thing that always confuse me. So having the code below:

    we could say, that both expressions are, in some way, an r-value references but the only difference between the first and the second one, is the first one (const int& i) cannot be modify, and the second one (int&& x) can be modify? or i'm just totally confused. Thanks for your time.

    Best regards, Aitor

    • Alex

      Both of the above are l-value references. The first is a const l-value reference assigned to r-value 10. In the latter, the second ampersand is essentially ignored -- named r-value references are l-values! So this becomes non-const l-value reference assigned to r-value 10. Remember, l-value and r-value are properties of expressions, not variables. We use the term r-value reference not to denote that the variable is an r-value itself, but to denote the type of expressions that it can reference.

  • ty

    Hi, dear Alex, May I ask when you say

    Const references can accept any type of argument, including l-values, const l-values, and r-values.

    the r-values. How come when not pass by const reference we cant recevied the r-values but when we declare a const parameter we can pass the r- values? r-value are literals right? they do not have address am i right thanks so much!

    • Alex

      r-values can be literals or temporary values. When you bind a const reference to an r-value, the duration of the r-value is extended to match the reference. This is useful because it allows us to pass r-values to functions by reference! Otherwise we'd have to pass them by value, which requires making a copy (or in C++11, by r-value reference).

  • D Brown

    In chapter 6 on question 2 I believe in the solution you passed a structure to the function and it was void because it changed the argument. I was very confused since I'm not sure we had done this before. Would be it be appropriate to add a note since its explained after the fact? I apologize if it is explained before that.

  • KG

    You have written: "Some programmers and companies feel this is a big enough program to advise not passing by reference this way..."

    I'm guessing you meant to write "big enough problem..." instead?

    This is all fantastic stuff by the way, I've been meaning to learn C++ for quite some time but always felt a little intimidated, but perhaps it's not quite as complicated as I had led myself to believe.


    Hello Alex. I refer learn c++ almost everyday. I respect you as a ubiquitous tutor.  
    You say that
    Disadvantages of passing by reference:
    Because a non-const reference cannot be made to an non-const l-value or an r-value (e.g. a literal or an expression)

    But, I think that
    Because a non-const reference cannot be made to an const l-value or an r-value (e.g. a literal or an expression)

    Is it correct or not?

Leave a Comment

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