Search

7.4a — Returning values by value, reference, and address

In the three previous lessons, you learned about passing arguments to functions by value, reference, and address. In this section, we’ll consider the issue of returning values back to the caller via all three methods.

As it turns out, returning values from a function to its caller by value, address, or reference works almost exactly the same way as passing arguments to a function does. All of the same upsides and downsides for each method are present. The primary difference between the two is simply that the direction of data flow is reversed. However, there is one more added bit of complexity -- because local variables in a function go out of scope and are destroyed when the function returns, we need to consider the effect of this on each return type.

Return by value

Return by value is the simplest and safest return type to use. When a value is returned by value, a copy of that value is returned to the caller. As with pass by value, you can return by value literals (e.g. 5), variables (e.g. x), or expressions (e.g. x+1), which makes return by value very flexible.

Another advantage of return by value is that you can return variables (or expressions) that involve local variables declared within the function without having to worry about scoping issues. Because the variables are evaluated before the function returns, and a copy of the value is returned to the caller, there are no problems when the function’s variable goes out of scope at the end of the function.

Return by value is the most appropriate when returning variables that were declared inside the function, or for returning function arguments that were passed by value. However, like pass by value, return by value is slow for structs and large classes.

When to use return by value:

  • When returning variables that were declared inside the function
  • When returning function arguments that were passed by value

When not to use return by value:

  • When returning a built-in array or pointer (use return by address)
  • When returning a large struct or class (use return by reference)

Return by address

Returning by address involves returning the address of a variable to the caller. Similar to pass by address, return by address can only return the address of a variable, not a literal or an expression (which don’t have addresses). Because return by address just copies an address from the function to the caller, return by address is fast.

However, return by address has one additional downside that return by value doesn’t -- if you try to return the address of a variable local to the function, your program will exhibit undefined behavior. Consider the following example:

As you can see here, value is destroyed just after its address is returned to the caller. The end result is that the caller ends up with the address of non-allocated memory (a dangling pointer), which will cause problems if used. This is a common mistake that new programmers make. Many newer compilers will give a warning (not an error) if the programmer tries to return a local variable by address -- however, there are quite a few ways to trick the compiler into letting you do something illegal without generating a warning, so the burden is on the programmer to ensure the address they are returning will be to a valid variable after the function returns.

Return by address was often used to return dynamically allocated memory to the caller:

This works because dynamically allocated memory does not go out of scope at the end of the block in which it is declared, so that memory will still exist when the address is returned back to the caller. Keeping track of manual allocations can be difficult. Separating the allocation and deletion into different functions makes it even harder to understand who’s responsible for deleting the resource or if the resource needs to be deleted at all. Smart pointers (covered later) and types that clean up after themselves should be used instead of manual allocations.

When to use return by address:

  • When returning dynamically allocated memory and you can’t use a type that handles allocations for you
  • When returning function arguments that were passed by address

When not to use return by address:

  • When returning variables that were declared inside the function or parameters that were passed by value (use return by value)
  • When returning a large struct or class that was passed by reference (use return by reference)

Return by reference

Similar to pass by address, values returned by reference must be variables (you should not return a reference to a literal or an expression that resolves to a temporary value, as those will go out of scope at the end of the function and you’ll end up returning a dangling reference). When a variable is returned by reference, a reference to the variable is passed back to the caller. The caller can then use this reference to continue modifying the variable, which can be useful at times. Return by reference is also fast, which can be useful when returning structs and classes.

However, just like return by address, you should not return local variables by reference. Consider the following example:

In the above program, the program is returning a reference to a value that will be destroyed when the function returns. This would mean the caller receives a reference to garbage. Fortunately, your compiler will probably give you a warning or error if you try to do this.

Return by reference is typically used to return arguments passed by reference to the function back to the caller. In the following example, we return (by reference) an element of an array that was passed to our function by reference:

This prints:

5

When we call getElement(array, 10), getElement() returns a reference to the array element with index 10. main() then uses this reference to assign that element the value 5.

Although this is somewhat of a contrived example (because you can access array[10] directly), once you learn about classes you will find a lot more uses for returning values by reference.

When to use return by reference:

  • When returning a reference parameter
  • When returning an element from an array that was passed into the function
  • When returning a large struct or class that will not be destroyed at the end of the function (e.g. one that was passed in)

When not to use return by reference:

  • When returning variables that were declared inside the function or parameters that were passed by value (use return by value)
  • When returning a built-in array or pointer value (use return by address)

Mixing return references and values

Although a function may return a value or a reference, the caller may or may not assign the result to a value or reference accordingly. Let’s look at what happens when we mix value and reference types.

In case A, we’re assigning a reference return value to a non-reference variable. Because value isn’t a reference, the return value is copied into value, as if returnByReference() had returned by value.

In case B, we’re trying to initialize reference ref with the copy of the return value returned by returnByValue(). However, because the value being returned doesn’t have an address (it’s an r-value), this will cause a compile error.

In case C, we’re trying to initialize const reference cref with the copy of the return value returned by returnByValue(). Because const references can bind to r-values, there’s no problem here. Normally, r-values expire at the end of the expression in which they are created -- however, when bound to a const reference, the lifetime of the r-value (in this case, the return value of the function) is extended to match the lifetime of the reference (in this case, cref)

Lifetime extension doesn’t save dangling references

Consider the following program:

In the above program, returnByReference() is returning a const reference to a value that will go out of scope when the function ends. This is normally a no-no, as it will result in a dangling reference. However, we also know that assigning a value to a const reference can extend the lifetime of that value. So which takes precedence here? Does 5 go out of scope first, or does ref extend the lifetime of 5?

The answer is that 5 goes out of scope first, then the reference to 5 is copied back to the caller, and then ref extends the lifetime of the now-dangling reference.

However, the following does work as expected:

In this case, the literal value 5 is first copied back into the scope of the caller (main), and then ref extends the lifetime of that copy.

Returning multiple values

C++ doesn’t contain a direct method for passing multiple values back to the caller. While you can sometimes restructure your code in such a way that you can pass back each data item separately (e.g. instead of having a single function return two values, have two functions each return a single value), this can be cumbersome and unintuitive.

Fortunately, there are several indirect methods that can be used.

As covered in lesson 7.3 -- Passing arguments by reference, out parameters provide one method for passing multiple bits of data back to the caller. We don’t recommend this method.

A second method involves using a data-only struct:

A third way (introduced in C++11) is to use std::tuple. A tuple is a sequence of elements that may be different types, where the type of each element must be explicitly specified.

Here’s an example that returns a tuple, and uses std::get to get the nth element of the tuple:

This works identically to the prior example.

You can also use std::tie to unpack the tuple into predefined variables, like so:

As of C++17, a structured binding declaration can be used to simplify splitting multiple returned values into separate variables:

Using a struct is a better option than a tuple if you’re using the struct in multiple places. However, for cases where you’re just packaging up these values to return and there would be no reuse from defining a new struct, a tuple is a bit cleaner since it doesn’t introduce a new user-defined data type.

Conclusion

Most of the time, return by value will be sufficient for your needs. It’s also the most flexible and safest way to return information to the caller. However, return by reference or address can also be useful, particularly when working with dynamically allocated classes or structs. When using return by reference or address, make sure you are not returning a reference to, or the address of, a variable that will go out of scope when the function returns!

Quiz time

Write function prototypes for each of the following functions. Use the most appropriate parameter and return types (by value, by address, or by reference), including use of const where appropriate.

1) A function named sumTo() that takes an integer parameter and returns the sum of all the numbers between 1 and the input number.

Show Solution

2) A function named printEmployeeName() that takes an Employee struct as input.

Show Solution

3) A function named minmax() that takes two integers as input and returns back to the caller the smaller and larger number in a std::pair. A std::pair works identical to a std::tuple but stores exactly two elements.

Show Solution

4) A function named getIndexOfLargestValue() that takes an integer array (as a std::vector), and returns the index of the largest element in the array.

Show Solution

5) A function named getElement() that takes an array of std::string (as a std::vector) and an index and returns the array element at that index (not a copy). Assume the index is valid, and the return value is const.

Show Solution

7.5 -- Inline functions
Index
7.4 -- Passing arguments by address

243 comments to 7.4a — Returning values by value, reference, and address

  • A

    Hello, how do I change a pointer returned from a function?

    what I want is a function that returns a pointer that I can use. Instead of assigning ptr to something using

    I want to be able to asign ptr to something using a function

  • Nguyen

    Hi,
    "When not to use return by reference:
    When returning variables that were declared inside the function (use return by value)"

    I guess we should not also return a function parameter that is not a reference to the argument.
    For example:

    I thought a reference to variable x was passed back to the caller, but the copy of x was returned to the caller.

    I think the following lines are the same but I can't find any good reason to prove they are the same.
    [/code]
    int& getValue(int x)
    same as int getValue(int x)
    [code}

    • They're not the same. Parameters, just like variables declared inside the function, should not be returning by reference or pointer. Your example causes undefined behavior. Your compiler should've warned you, make sure you set it up according to lessons 0.10, 0.11.

    • Alex

      Yep, you shouldn't return a reference to a function parameter that was passed by value, because the parameter will be destroyed at the end of the function.

      Your code should exhibit undefined behavior, as parameter x is destroyed at the end of the function -- but you're passing a reference to it back to the caller and assigning a value to it.

      • Nguyen

        "Yep, you shouldn't return a reference to a function parameter that was passed by value, because the parameter will be destroyed at the end of the function."

        Why is it ok to return a reference to a function parameter that is passed by reference since that reference parameter will be also destroyed at the end of the function?

        Thanks

  • solaris

    Hi,
    How to return multiple values from a member function of a class which is defined in another file ?

  • Meghana

    Shouldn't the solution to quiz question 4 should be

    ?

  • Idk why this is giving me undefined behavior, I got really confused from the previous lessons and I don't know what the problem is. I feel very stupid.

    And I was just wondering why in the function

    value was "Const" because isn't that the value you're going to use for the addition of the sum of all the numbers between 1 and the input number

    • Hi!

      Line 6 compares @x to @userInput before every cycle of the loop. Since you're increasing @userInput inside the loop (userInput += x), the loop will never stop. You need a new variable to either store the sum.

      > And I was just wondering why in the function value was "Const"
      const is usually only applied to parameters that are pointers or references. Declaring @value const makes it immutable (ie. it can't be modified). If you add a variable to store the sum, you're not going to modify @value anymore.

  • shri

    It is mentioned in this chapter that:

    When to use return by reference:
    - When returning a reference parameter

    I did not understand why we would want to return a reference parameter when that variable already exists in the calling function.

    For example, say we had the following code:

    Here, I do not need to return anything from "return_built_in_array" because array1 is in scope within function main(), so I have no need of returning array2 as a reference from the function "return_built_in_array".

  • shri

    Hi Alex and Nascardriver,

    I wanted to compare 2 things and understand why 1) works but 2) does not. Please reply, if my understanding is correct.

    1)

    1) This works. Is it because, returnByValue() returns an `int` `5` which is stored in main's memory stack and cref is a reference to this memory stack?

    2) This does not work because, when returning `5` `returnByReference()` creates a reference to stack of memory where `5` is stored. This stack of memory where `5` is stored goes out of scope, so the reference returned by function `returnByReference()`is pointing to an out of scope memory address. In main , `ref` is again a reference to a reference which is pointing to an out of scope memory address.

    Is my understanding correct?

    • Hi Shri!

      I don't like explaining things with heap and stack, because it's not standardized (ie. the standard doesn't care, so implementations can take memory from wherever they want).

      Both functions create the 5 in their own scope. When the scope ends, the 5 dies.
      @returnByValue returns a copy of 5, this 5 now lives in @main, so it can be referenced.
      @returnByReference returns a reference to its local 5, this 5 dies at the end of @returnByReference, so @main references a value that is no longer safe to access.

      • Shri

        Got it! Thanks for the explanation Nascardriver!

        1 question I have regarding your reply is:
        @returnByReference returns a reference to its local 5, this 5 dies at the end of @returnByReference, so @main references a value that is no longer safe to access.

        Shouldn't this be:
        @returnByReference returns a reference to its local 5, this 5 dies at the end of @returnByReference, so @main references a reference which in turn references a value that is no longer safe to access.

  • Shri

    I did not understand why pass by address should be used while returning a built-in-array, why can't we use pass by reference for this?

    • Because your function will only work with arrays of the specified size. Passing/returning by address doesn't have the array's size information, so you can pass/return every size.
      If you need the size (eg. for for-each loops), you can pass/return by reference.
      There's rarely a reason to use built-in arrays, as @std::vector and @std::array are easier to use and have more functionality.

      • Shri

        Thanks for replying Nascardriver. I understood the issue thanks to your reply.

        I also tried the following examples so as to fortify my understanding, just posting in case someone else gets the same doubt.

        Works:

        doesn't work:

        • That's a compilation error because it's the wrong syntax.

          Compiles and behaves as expected.

          You can pass and return arrays by reference, but it's more difficult than using std containers.

  • Matty J

    Hey guys, I gotta thank you for putting in all the effort to building this tutorial site - it's really helped me so far!

    I noticed that you're rewriting and reorganizing the site, so I figured I'd put in my two cents to help this section:

    1) I had to look up what the asterisk in int* function(); and the ampersand in int& function(); meant. I know that you probably touched on returning types when discussing the building of functions, but this is such fresh information at this point in the tutorial for me, I was really having a tough time placing the use of these two symbols. Having a reminder or refresher would have definitely helped.

    2) The section on tuples appears haphazard to me, and there's all of these new std:: terms to remember regarding tuples at the end of the section. And then the quiz doesn't even touch on tuples at all... it might be better to move this to a 7.4b or perhaps add more quiz questions to really hammer in these concepts - a chapter seven pass/return quiz in the early parts of the chapter that really knocks this syntax in your head?

    Of course I write all of this and I'm coming off as the "idea guy." The guy with all of the ideas and none of the execution/implementation! Ha! Do with my unsolicited advice what you will

  • caja

    Hello, I was trying to execute a program in section return by reference in CodeBlocks and i get the following error:

    C:\CBProjects\Vezba\main.cpp|9|error: conversion to 'std::array<int, 25u>::size_type {aka unsigned int}' from 'int' may change the sign of the result [-Werror=sign-conversion]|
    ||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

    I wasn't sure if it was something I did, so i copied entire code, to make sure there are no typing mistakes.
    Can you help me with this? Thank you very much.

    • Hi Caja!

      @std::array::operator[] expects an unsigned integer type. @index is a signed int. Conversion from signed to unsigned can be problematic. To fix this, you can change the type of @index or cast it.

  • TYGuy

    Very useful examples. Thanks

  • Gonor

  • Clapfish

    Hello!

    I tried compiling the final code snippet of this lesson (after ensuring I changed my compiler settings from the C++14 to the C++17 standard) with the GNU GCC Compiler that comes with CodeBlocks, and received the following errors:

    ||=== Build: Debug in Playground (compiler: GNU GCC Compiler) ===|
    ||In function 'int main()':|
    |11|error: expected unqualified-id before '[' token|
    |12|error: 'a' was not declared in this scope|
    |12|error: 'b' was not declared in this scope|
    ||=== Build failed: 3 error(s), 0 warning(s) (0 minute(s), 1 second(s)) ===|

    Any ideas why that might be?

    • Sure sounds like your compiler doesn't know c++17. But if that was to case it should not even start compiling and complain that it doesn't know the command line option to set the standard to c++17. First of all, update your compiler. Try again. If it doesn't work, try compiling manually (g++ -std=c++17 ./main.cpp). If it still doesn't work, try a different compiler.
      g++ 8.2.0-9 compiles the code without errors.

      • Clapfish

        Thanks nascardriver! I thought this was a good opportunity to play with adding/changing compilers for a bit more experience.

        I found a MinGW 64bit installer with g++ 8.1.0 included. Seems to be doing the trick nicely now that I've got CodeBlocks pointing at it - compiles the aforementioned code fine, and seems notably snappier than the previous compiler (I think was version 5 or so, and was 32bit).

        I got a whole host of interesting errors initially with validation.cpp (which you might by now be familiar with having looked at my previous code) meaning I had to re-create that file. Despite being syntactically identical (including filename), that fixed the issue. I guess it was a CodeBlocks mix-up of some kind...

        Thanks again!

        • Good to hear. Clean your project after changing compiler settings (or the compiler itself) to make sure you're not getting bugs caused by mixed up files. By "clean" I mean removing all compiler-generated files. IDEs usually have a button to do this ("Clean Project", "Clean Build", or similar). If codeblocks doesn't have this, just delete all files that aren't source- or project files (Back up your files first if you're not sure what you're doing).

          • Clapfish

            Perfect timing! I was just about to edit my previous comment when I'd seen you'd already replied, because after posting it I tested my BlackJack project which was producing similar (and much more numerous, being split into so many files) errors which left me a bit bewildered.

            Build -> Clean = solved! :)

            Thank you!

  • Clapfish

    Hi Alex!

    A bit of inconsistency right at the top here:

    "In the three previous lessons, you learned about passing arguments to functions by value, reference, and address. In this section, we’ll consider the issue of returning values back to the caller via all three methods.

    As it turns out, returning values from a function to its caller by value, address, or reference works almost exactly the same way as passing parameters to a function does."

    '...passing arguments to functions...' followed by '...passing parameters to a function...'
    ---

    And a typo under the first code snippet of the "Return by address" section:

    "This is a common mistakes that new programmers make." (-s)

  • Silviu

    Hello, i have some questions, i'm at the 9 chapter and i want to understand the pointer *this better:

    ok it works.
    So if we put:

    in the precedent example i needed a lvalue to work.
    What i don't understand better the reference"&" in front of the type.
    The only thing i see, when we need to return strictly by that literal, here in the example i mean by 3 and in the first example where we want, depending on the situation to declare our own variable in the main function.

    Second question is about int* ?

    So in Alex examples works:

    I know what is doing here, but i don't understand very well the int* ?
    I did understand how to use it like: int hey(int *x){} inside the () but not int* .
    Or this int*  - int* allocateArray(int size) works just when we dynamically allocate memory.
    Thank you

    • Hi Silviu!

      1. You're returning by value in both cases. Case 1 accepts a reference to an int as parameter, but the return type is "int", not "int&".
      If you want to pass an rvalue by reference you can use "const int &"
      2. int* is the return type. @new allocates new memory and returns a pointer, that pointer is being returned.
      @hey doesn't work, because @x is an int, not an int*.

      I feel like you're not all to confident about return values and parameters/argument. Give lesson 1.4 and 1.4a another read.

  • Paul

    Hi,
    I've just wanted to test this dangling reference.

    It's working fine, but it shouldn't right? Or have I missed something?
    I used Visual Studio Community 2017

    • Behavior is undefined. It could work, it could fail. Adding more code is likely to change the results.

  • Olivia

    Hi, Alex. I think for line4 and line11 in the last example the name of the function should be returnTuple? Just to avoid confusion.

  • Andi

    This structured binding declaration as of C++17 is such a convenient way to return multiple values without the hassle of structs or extracting the tuple's elements with the lengthy std::get<0>(t) syntax.
    However, you only get to know about the data types checking std::make_tuple(...). Maybe it is worth a note that one can declare the variables before and then use std::tie() to extract the values.
    This

    is equivalent to

  • 1. i don't understand the difference between "Lifetime extension doesn’t save dangling references" and its previous section regarding references if the literal "5"
    goes out of scope in both versions what difference does it make to return it as a "const int&" or as an "int" to the variable "const int &ref" within its caller,
    shouldn't both provide just a copy ?

    2. i think in the same section in Code Line: 8 there is a typo "returnByValue()" while function is called "returnByReference()"

    • Alex

      No, if you return a const int& then it will return a reference, not a copy. And if you return a reference to a value that goes out of scope at the end of the function, you'll return a dangling reference. Lifetime extension does not save the value going out of scope at the end of the function.

      Typo fixed!

  • Matt

    Hi Alex and co, I've come back to this lesson as I've realised there's something that's not really clicking. What's the purpose of returning a const from a function?

    For example:

    Is there any point in returning a const by value from a function? After testing it seems it can be assigned to a const or a non const:

    The opposite also seems true:

    Both seems fine by the compiler, so am I missing something, is there no point in ever returning a const by value?

    When it comes to return by reference, the only time I can see it making a difference is if you're trying to a return an r-value, which requires the reference to be const. Apart from that, I don't see any other reasons why it would be needed? Seeing as it doesn't seem to make any difference whether it's assigned to a const or a non-const in main()?

    Finally, can anyone explain this? From this very lesson:

    I added the two output statements, interestingly, the first cout outputs 5, but the second cout outputs the garbage value:
    5
    -858993460

    why is the first output fine, but not the second?

    I suspect I'm being dense, but something just isn't clicking when it comes to const returns, so if you can try and shed some light or link me to a good lesson (either on here or elsewhere) that would be great. Thanks again for all your help!

    • Hi Matt!

      > Is there any point in returning a const by value from a function?
      No. If you're returning by value, const is pointless.

      > When it comes to return by reference
      Returning by value is slow, so you return by reference. References allow the caller to modify the value, which, in most cases, shouldn't be allowed. So you use const references.

      > why is the first output fine, but not the second?
      You're returning a temporary by value. Behavior is undefined. You might get the correct value, you might get a wrong value, you might crash.

  • Hector

    Hi...
    const references preserve temporary r-values(expressions and literals) and thus extend their life.This happens in case of passing parameters to a function and in the same function,then why does it not happen in case of returning from a function?
    CASE 1:-Within same function---VALID

    CASE 2:-Passing to a function---VALID

    CASE 3:-Returning from a function---INVALID

    • Alex

      This is a common enough question that I added a new subsection to the lesson entitled, "Lifetime extension doesn't save dangling references" to address.

  • Omkar

    #include <array>
    #include <iostream>

    // Returns a reference to the index element of array
    int& getElement(std::array<int, 25> &array, int index)
    {
        // we know that array[index] will not be destroyed when we return to the caller (since the caller passed in the array in the first place!)
        // so it's okay to return it by reference
        return array[index];
    }

    int main()
    {
        std::array<int, 25> array;

        // Set the element of array with index 10 to the value 5
        getElement(array, 10) = 5;
        
        std::cout << array[10] << '\n';

        return 0;

    In the above piece of code aren't we trying to do something like this when we call getElement(array,10):
    int &ref = 5 which is illegal? or does this work differently ? Or is it because array[index] which is being returned by reference not a r value ?

  • wolfenste

    "A third method is to restructure your code in such a way that you can pass back each data item separately (e.g. instead of having a single function return two values, have two functions each return a single value)."

    Ok sir, but isn't this just the classic way - one function, one returned value? I mean, it is not 'returning multiple values'.

  • David

    Are std::array and std::vector automatically passed and returned by address? For example, does the following function just pass the address of x in and out? Or does it copy the elements of x?

    • nascardriver

      Hi David!

      Your code doesn't work, because you didn't specify the type of the vector.
      Returning an std::array or std::vector will create a copy, if you want to return it by reference you need to use &.

      • David

        Hi nascardriver! Thank you!

        If I create a std::vector and pass it by reference, does it get destroyed? For example:

        • nascardriver

          Your code doesn't work, because you put the & in the wrong place.

          You're returning a temporary by reference, which will most likely cause your program to crash. @x is returned but gets destroyed before it can be used anywhere else.

          This will make more sense after lesson 8.2 (Classes and class members).

          • David

            Ok thank you! Previous lessons suggested using std::vector when dynamically allocating memory, but it seems that I should still use pointers when I need to return an array created within a function. Is that right?

            • nascardriver

              Your compiler should apply return value optimization so you're not actually creating a copy of the array. If you don't want to rely on your compiler but still want the benefits if std::vector you can pass it as a parameter by reference instead of returning it.

              • David

                Ok thank you! Although now I'm a little confused, because your first comment says returning a std::vector will create a copy but now it sounds like you are saying the compiler does something else. Sorry if I misunderstood you! I'm still a newbie :-/

                • nascardriver

                  If the compiler wouldn't do optimization (which you can't rely on it does), the vector is returned by copy. The optimization only affects performance, not behavior. You don't have to worry about accidentally having a reference instead of a copy.

  • Matt

    • nascardriver

      Hi Matt!

      All cool, you don't need the 'const' keyword for non-reference parameters since it doesn't really do anything other then preventing you from accidentally modifying it.
      Your alternative MinMax should perform better than the struct-based one. Passing custom objects by value is rarely a good idea. I wouldn't be surprised if your struct was optimized away by the compiler though.

  • ASP

    Hi Alex, It would be nice if you could add in this lesson about the possiblity of returning or passing back multiple values from the functions with each return methods. Thanks.

  • merocom

    how does return with void function

    • nascardriver

      Hi merocom!

      The word "return" might have been a bad choice here, since @minmax doesn't actually return anything. Instead, it sets the value of @minOut and @maxOut.
      Here's an example of what the definition of @minmax could look like.

    • Alex

      Technically it is returning a value back to the caller, just via a parameter rather than a return value.

      However, to be clearer, I updated the wording from "returns" to "passes back to the caller".

  • merocom

    Quiz2 modification

    • nascardriver

      Hi merocom!

      Line 4: Don't use 'using namespace'
      Line 22: You don't need the '=' sign

      Works just as well
      @main: Missing return statement.

  • Micah

    "In case C, we’re trying to initialize const reference ref with the copy of the return value returned by returnByValue()"

    Shouldn't it be:

    "In case C, we’re trying to initialize const reference cref with the copy of the return value returned by returnByValue()"

    changing "ref" to "cref"

  • Micah

    Couldn’t you also return a static memory address when returning by address to trick the local scope of the function?

    Or is it better not to do this because it can’t be deallocated like dynamically allocated memory?

    Not sure if there’d be any situation when you wanted to be absolutely sure the empty memory you allocated didn’t get deallocated or not.

    Actually not even sure if it’s impossible to deallocate a static address.

    • nascardriver

      Hi Micah!

      Without testing I'd say this won't work. The problem here is that you're returning the address to a local variable that is not static. @newInt will be gone after the return and @ptr will point to an invalid address.

      You could declare @newInt to be static and the code would work. There's also no need to store the pointer locally.

      Although I make use of this from time to time I don't think it's good practice.

      • Alex

        Although nascardriver's version is mostly safe (newInt won't go out of scope at the end of the function, so you could return the address and the caller could use it) I'm not sure there are any actual cases where you'd want to do this. Why not just return newInt by value?

        I say "mostly" because this could cause issues in a multithreaded environment. Alternatively, if the callers were silly enough to hold onto the address, they might find the value had changed under their noses due to another function call. After all, this is essentially acting as a global variable, just with a more limited scope.

Leave a Comment

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