Search

2.2 — Function return values

Consider the following program:

This program is composed of two conceptual parts: First, we get a value from the user. Then we tell the user what double that value is.

Although this program is trivial enough that we don’t need to break it into multiple functions, what if we wanted to? Getting an integer value from the user is well-defined job that we want our program to do, so it would make a good candidate for a function.

So let’s write a program to do this:

While this program is a good attempt at a solution, it doesn’t quite work.

When function getValueFromUser is called, the user is asked to enter an integer as expected. But the value they enter is lost when getValueFromUser terminates and control returns to main. Variable num never gets initialized with the value the user entered, and so the program always prints the answer 0.

What we’re missing is some way for getValueFromUser to return the value the user entered back to main so that main can make use of that data.

Return values

When you write a user-defined function, you get to determine whether your function will return a value back to the caller or not. To return a value back to the caller, two things are needed.

First, your function has to indicate what type of value will be returned. This is done by setting the function’s return type, which is the type that is defined before the function’s name. In the example above, function getValueFromUser has a return type of void, and function main has a return type of int. Note that this doesn’t determine what specific value is returned -- only the type of the value.

Second, inside the function that will return a value, we use a return statement to indicate the specific value being returned to the caller. The specific value returned from a function is called the return value. When the return statement is executed, the return value is copied from the function back to the caller. This process is called return by value.

Let’s take a look at a simple function that returns an integer value, and a sample program that calls it:

When run, this program prints:

5
7

Execution starts at the top of main. In the first statement, the function call to returnFive is evaluated, which results in function returnFive being called. Function returnFive returns the specific value of 5 back to the caller, which is then printed to the console via std::cout.

In the second function call, the function call to returnFive is evaluated, which results in function returnFive being called again. Function returnFive returns the value of 5 back to the caller. The expression 5 + 2 is evaluated to produce the result 7, which is then printed to the console via std::cout.

In the third statement, function returnFive is called again, resulting in the value 5 being returned back to the caller. However, function main does nothing with the return value, so nothing further happens (the return value is ignored).

Note: Return values will not be printed unless the caller sends them to the console via std::cout. In the last case above, the return value is not sent to std::cout, so nothing is printed.

Fixing our challenge program

With this in mind, we can fix the program we presented at the top of the lesson:

When this program executes, the first statement in main will create an int variable named num. When the program goes to initialize num, it will see that there is a function call to getValueFromUser, so it will go execute that function. Function getValueFromUser, asks the user to enter a value, and then it returns that value back to the caller (main). This return value is used as the initialization value for variable num.

Compile this program yourself and run it a few times to prove to yourself that it works.

Void return values

Functions are not required to return a value. To tell the compiler that a function does not return a value, a return type of void is used. Let’s look at the doPrint() function from the previous lesson:

This function has a return type of void, indicating that it does not return a value to the caller. Because it does not return a value, no return statement is needed (trying to return a specific value from a function with a void return type will result in a compilation error).

Here’s another example of a function that returns void, and a sample program that calls it:

In the first function call to function returnNothing, the function prints “Hi” and then returns nothing back to the caller. Control returns to main and the program proceeds.

The second function call to function returnNothing won’t even compile. Function returnNothing has a void return type, meaning it doesn’t return a value. However, this statement is trying to send the return value of returnNothing to std::cout to be printed. std::cout doesn’t know how to handle this (what value would it output?). Consequently, the compiler will flag this as an error. You’ll need to comment out this line of code in order to make your code compile.

A void return type (meaning nothing is returned) is used when we want to have a function that doesn’t return anything to the caller (because it doesn’t need to). In the above example, the returnNothing function has useful behavior (it prints “Hi”) but it doesn’t need to return anything back to the caller (in this case, main). Therefore, returnNothing is given a void return type.

Returning to main

You now have the conceptual tools to understand how the main function actually works. When the program is executed, the operating system makes a function call to main. Execution then jumps to the top of main. The statements in main are executed sequentially. Finally, main returns an integer value (usually 0) back to the operating system. This is why main is defined as int main().

Why return a value back to the operating system? This value is called a status code, and it tells the operating system (and any other programs that called yours) whether your program executed successfully or not. By consensus, a return value of 0 means success, and a non-zero return value means failure.

Best practice

Your main function should return 0 if the program ran normally, or a non-zero value if it encountered an error and could not complete as expected.

Note that the C++ specification explicitly specifies that function main must return an int. Some compilers will invalidly let you specify a void return type (they will implicitly return 0 if you do this), but you should not rely on this.

For now, you should also define your main() function at the bottom of your code file, below other functions.

A few additional notes about return values

First, if a function has a non-void return type, it must return a value of that type (using a return statement). Failure to do so will result in undefined behavior. The only exception to this rule is for function main(), which will assume a return value of 0 if one is not explicitly provided. That said, it is best practice to explicitly return a value from main, both to show your intent, and for consistency with other functions (which will not let you omit the return value).

Best practice

Always explicitly provide a return value for any function that has a non-void return type.

Warning

Failure to return a value from a function with a non-void return type (other than main) will result in undefined behavior.

Second, when a return statement is executed, the function returns back to the caller immediately at that point. Any additional code in the function is ignored.

Third, a function can only return a single value back to the caller each time it is called. However, the value doesn’t need to be a literal, it can be the result of any valid expression, including a variable or even a call to another function that returns a value. In the getValueFromUser() example above, we returned a variable holding the number the user typed.

Finally, note that a function is free to define what its return value means. Some functions use return values as status codes, to indicate whether they succeeded or failed. Other functions return a calculated or selected value. Other functions return nothing. What the function returns and the meaning of that value is defined by the function’s author. Because of the wide variety of possibilities here, it’s a good idea to document your function with a comment indicating what the return values mean.

For example:

Reusing functions

Now we can illustrate a good case for function reuse. Consider the following program:

While this program works, it’s a little redundant. In fact, this program violates one of the central tenets of good programming: “Don’t Repeat Yourself” (often abbreviated “DRY”).

Why is repeated code bad? If we wanted to change the text “Enter an integer:” to something else, we’d have to update it in two locations. And what if we wanted to initialize 10 variables instead of 2? That would be a lot of redundant code (making our programs longer and harder to understand), and a lot of room for typos to creep in.

Let’s update this program to use our getValueFromUser function that we developed above:

This program produces the following output:

Enter an integer: 5
Enter an integer: 7
5 + 7 = 12

In this program, we call getValueFromUser twice, once to initialize variable x, and once to initialize variable y. That saves us from duplicating the code to get user input, and reduces the odds of making a mistake. Once we know getValueFromUser works for one variable, it will work for as many of them as we need.

This is the essence of modular programming: the ability to write a function, test it, ensure that it works, and then know that we can reuse it as many times as we want and it will continue to work (so long as we don’t modify the function -- at which point we’ll have to retest it).

Best practice

Follow the DRY best practice: “don’t repeat yourself”. If you need to do something more than once, consider how to modify your code to remove as much redundancy as possible. Variables can be used to store the results of calculations that need to be used more than once (so we don’t have to repeat the calculation). Functions can be used to define a sequence of statements we want to execute more than once. And loops (which we’ll cover in a later chapter) can be used to execute a statement more than once.

Conclusion

Return values provide a way for functions to return a single value back to the function’s caller.

Functions provide a way to minimize redundancy in our programs.

Quiz time

Question #1

Inspect the following programs and state what they output, or whether they will not compile.

1a)

Show Solution

1b)

Show Solution

1c)

Show Solution

1d)

Show Solution

1e)

Show Solution

1f)

Show Solution

1g)

Show Solution

1h) Extra credit:

Show Solution

Question #2


What does “DRY” stand for, and why is it a useful practice to follow?

Show Solution


2.3 -- Introduction to function parameters and arguments
Index
2.1 -- Introduction to functions

56 comments to 2.2 — Function return values

  • hamza

    why main() is not declared void as void setup() and void loop() in arduino programming?

    • nascardriver

      The return value of `main` is the return value of the program. Other programs can use the return value of `main`.
      On Arduino, there are no other programs, so there doesn't have to be a return value.

  • Fernando Só

    I have a question. I tried to do this code by myself, with different names and so on:

    ____________________________________________________________________________
    #include <iostream>

    int getValueFromUser() // this function now returns an integer value
    {
        std::cout << "Enter an integer: ";
        int input{};
        std::cin >> input;  

        return input; // return the value the user entered back to the caller
    }

    int main()
    {
        int num { getValueFromUser() }; // initialize num with the return value of getValueFromUser()

        std::cout << num << " doubled is: " << num * 2 << '\n';

        return 0;
    }

    _________________________________________________________________________

    and when I run it ask me twice "Enter an integer:". Then i tried to copy this code and use it to test if it was me but the same thing happens. That's supposed to happen?

    • nascardriver

      No, that's not supposed to happen. This sounds like some previous code of yours caused the issue and now you're not recompiling the fixed version. Try changing a string in your code and see if it correctly changes in the program. If it doesn't change, you're not recompiling at all or you're compiling a wrong file.

  • Hi Alex,

    This is a great resource - one thing that may make it less confusing for people would be to use text when naming your variables. For example'

    maybe easier to understand for a beginner if the variable name was something like

    because seeing the '5' in the variable name may be causing people to think that is where the value is being specified...
    Just a thought!

  • Man, I have no clue what I did wrong... It won't even open this for me. Can anyone help?

    And yes, Nascardriver, if you're reading this, this was the opening to the game I was talking about. The "I'd like us to be friends, what's your name?" is placeholder for a different phrase, I haven't decided between 3 options yet.

    • The syntax highlighting (colors) already shows you where the error is. Line 6 and 7 don't look right.
      You need to use `<<` again to print more data.

      There's no need for `std::endl` in line 8, use '\n'.

      If you want to print some more data, not just a line feed, use `<<`.

  • Hi! So I was wondering if this bit of code could be improved upon...
    It does work as intended, but I'd like to do better.
    BTW Thank you so much for this! I've had about 5 people "teach" me by typing up their stuff, never explaining any of it, and just generally being lazy. I am using Microsoft Visual Studio 2019.

    • Hi!

      That's as simple as it's gonna get.
      You can remove the `0` from line 7, as you're never using it. Empty curly braces still initialize to `0`, but it's less likely to confuse the reader.

      • Thanks! Would you mind testing a mini text adventure (maybe 5 minutes length- maybe) If I post the code here? I'd like to make sure that
        A) It works,
        B) I have a decent storyline,
        and
        C) I'm not overcomplicating the code
        ...
        If you'd be fine with this, hit me up here, please. BTW you have some of the most helpful comments here, thanks for that.

  • Carl

    I have never programmed before and I am completely lost on 1e of the quiz. can someone please help me to understand:
    a: how getNumbers() was used to create two variables when, it looks to me that they were never declared
    b: how that when it does compile it only prints 5 and wont print 7

    thank you

    • Do you mean 1f?
      a: `getNumbers` doesn't declare any variables, literals can be returned right away.
      b: A functions stops when a `return`-statement is reached. Since `return 5` is first, `return 7` is unreachable.

  • Rand

    This is a real treasure.
    And you are first class teachers.
    Thank you for this journey.

  • Mike

    "In fact, this program violates one of the central 'tenants' of good programming: “Don’t Repeat Yourself”

    Should be 'tenets'

    Them homonyms will get you every time if you're not careful :)

  • Thanos

    Hello.

    The #include <iostream> directive is missing at some code examples in this section.

  • Parsa

    I have a question...

    when will a function give its return value and when will it execute its statements starting from the top?

    does it only give its return value when being called when the caller is outputting something?
    so the name of the function appears after operator<<..?
    or when it is used as an expression.

    • Function execution always starts at the top of a function. Every function with a non-void return type returns something (Unless you omit the return, resulting in undefined behavior).
      What you do with the return value is up to you. You can ignore it, you can print it, you can store it in variables, etc.

    • JMB

      Hello Parsa,
      The C++ is a kind of sequential execution, it executes the command line after line. So Whenever the function is called it return something If the function has return keyword. Definitely to return something the compiler executes all the statements of the function from top to bottom.

  • VerticalLimit

    Hi Nascardriver and Alex

    Please give me some pointers on how to fix this program. I have covered the study material up to S.4.2a thus this Q might be considered by you as "jumping the gun".. but nonetheless.

    small snipped of the program

    What Iam trying to understand is after returning the values with  userBirthDate() and initialising them to int cusp{ userBirthDate() } I cant run simple if statement against it as compiler just ignores it. What am I doing wrong?
    P.S (There are few easier ways to write this program but I chose to make it little more challenging by applying what I have learned thus far (S.4.2a))

    • Line 44: That's the comma operator, only `month` will be returned (Lesson O.3.4).
      Since `day` and `month` are very small, you can encode them into a single `int`, or a fixed-width integer.

      Assuming day < 256 and month < 256.

      Using bitwise operators

      Using arithmetic

      You'll learn about nicer ways of returning multiple values later.

      > I cant run simple if statement against it as compiler just ignores it
      You didn't include the code that you tried. Both `day` and `month` are 0 in your if-statement. `cusp` is unused. Your if-statement probably doesn't do what you intended.
      Make sure you set up your compiler according to lesson 0.10 and 0.11, it tells you what's wrong.

  • chayim

    Why does example 1h compile to print 1?

    • When a function is used without being called, it evaluates to the function's address. `std::cout <<` doesn't know how to print function addresses, so it converts the address to a `bool`. Since the function's address is non-zero, the bool is true and "1" is printed.

  • habeebullah

    under the fixing our challenge example, i wrote the code again but I was having a compile error on line 9. The error was that I was using round brackets instead of braces. why can't I use the round brackets for the int

  • Singh

    You guys are amazing and really very helpful, highly appreciated. I am glad I found this tutorial to start learning C++.

    Query: How can we call the value of any variable initialized from main() to any function (such as below).

    [code]
    #include <iostream>

    int function()
    {
        int a, sub;
        std::cin>>a;
        sub=a+total;  //How can we get to value of total in here from Main function if possible?
        std::cout<<"Total of both Nub and A is " <<sub;
        
        return sub;
    }

    int main()
    {   int total;
        
        std::cin>>total;
        
        std::cout<<"Double to Sub is " <<function() *2; //here will be the double of sub from function.
    return 0;
    }
    [\code]

    So how can we get the value of Total from main to function? thanks in advance.

  • WLM

    This is a wonderful tutor!Thank you!

    Question 1h is not compilled in my Code::Blocks. The reason given  is that return5 without parenthesis always will be true.

    • Hi!

      Your compiler prints a warning, because using a function like that is most likely undesired.
      Your compiler is treating warnings as errors, so it doesn't compile. This is a good setting, keep it like that.

  • Napalm

    When you start a new console project in visual studio, and the "return 0;" in main() is absent, seemingly by design. I'm sure it used to be be included automatically.

    I remember reading a thread on stack exchange some months ago where someone submitted code for review, and someone actually advised them "return 0 is not needed".

    Is there a case where it is absolutely necessary to include return 0?

    I'd be interested to know some thoughts on this considering this tutorial seems to favour using up to date syntax and breaking old and/or bad habits.

    • You never need to return 0 from `main`. If you omit `main`'s return statement, 0 is returned.
      For consistency with all other functions, you should include `return 0` in `main`, even if it doesn't change the outcome.

  • Chayim

    You did not mention that it's able to cout next line by \n shortly and it's not a must to use endl ,and also that in an expression it's needed ' ' left and right of \n '\n'.

  • Chayim

    Why do you need to enter 0 in the "int num" {0}? it's working { } without anything in it.

  • yiğit eren

    alex is this c++ 11 because i did this in my atom editor but i must do this int x(); because if i tried to do this int x{}; it's give me an error so this is different version or look like something???

  • yeko

    yeah good lesson but but in this lesson (i think only this one) i think not so boring  but i think it's boring little bit. Um how can i do like sometimes i don't want to read documentation i just read your blog not watch videos (c++). Yeah i said sometimes i am feel like "ah come on watch some league of legends and one more and watch how much you want" but i know i can't do this i am challenge my self what can i do???

  • abhijeet

    can anyone explain me the output of 1h). i'm getting 1 as output. i don't know how its working. it should have thrown error because of return5 in main function right?

  • Wilson

    Hi Alex,

    Thanks for writing this useful guide! I have a quick question..

    For "Extra Credit", my initial guess would've been it will not compile nor run properly. However, I've ran it and have gotten a random number (as you've pointed out).

    Why is it able to compile and output a result when the variable "return5" has not been instantiated?

    • Hi Wilson!

      Using a function without calling it (ie. without ()), gives you the address of the function (Where it lives in memory).
      @std::cout doesn't know how to print function addresses, so it converts it to a bool.
      Every non-zero value is true, so the program prints 1, or, if you set @std::boolalpha, true.

  • Helliarc

    I'm trying to build the logic in my mind, and the function in the return example has me "asking questions"...  Is it standard to ask a question before deciding where to place the answer?  Shouldn't we have a place to put an answer before we ask the question?  I'm just asking as a formatting perspective, I feel like if I'm going to ask the user for information, I should define the place the user will place the information, and what to do with it, before I ask them the question(cout << "the question"), but I can also see how it is more logical to ask the question, and define the location before we prompt for input in 'cin' so that we know 'cin' will be placed in the preceding int variable memory location, for readability purposes...  I'm just making sure that the way you have written it is the "right" way, if it doesn't matter, or if it should be changed...

    • Alex

      The rule of "define a variable as close to its first use as possible" indicates that it should go after the std::cout, because the output line doesn't need it.

      But in reality, it doesn't matter that much which comes first. The rule is there to ensure you're not doing things like defining all your variables at the top of the function, or somewhere far away from where you use them. It's not worth quibbling over a line or two.

      • Helliarc

        I really appreciate your diligence in trying to answer every question here...  Just saying thank you!  I'm on chapter 5.11 right now, going through your tutorials step by step.  Can't wait for OOP! You're doing a fine thing here for people that are willing to learn.

  • Yo I am able to understand that
    int return7()
    {
        return 7;
    }

    int return9()
    {
        return 9;
    will equal 16 but I do not get why or how or what this works. PLEASE EXPLAIN

    • Alex

      When this expression statement is evaluated:

      return7() calls the return7 function, which returns the value 7. return9() calls the return9 function, which returns the value 9.

      If we plug in those intermediate values, we get this:

      Which should make it clearer where 16 is coming from.

  • Vladislav Trnka

    Sentence 'Now we have can illustrate a good case for function reuse.' does not make sense.

  • Maria

    Under the Fixing Our Program example. On line 14 isn't the semi-colon supposed to be outside the brackets. When I tried to compile, it would give me some errors

Leave a Comment

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