Programming would not be the same without functions. It’s easy to see why functions are so essential: Just imagine having to code everything from scratch each time you implement a new program. But writing functions in C++ is everything but trivial. Read on for our pro tips on functions in C++.

What Is a C++ Function?

As in any programming language, a C++ function is a modular piece of code that accomplishes a certain task. It may accept parameters, return values and produce what’s known as “side effects,” such as writing to memory. If you’re an aspiring C++ programmer, you’re probably already familiar with the main() function, which features heavily in C++ but behaves a bit differently from other functions. We’ll look into why that is below. 

A lot of programming consists of replicating work that has been done before. To reduce redundancy, most programming languages maintain libraries to store useful, reusable code. In C++, the Standard Template Library (STL) offers a range of functions for manipulating data. In addition to functions, the STL contains templates for data containers like queues, algorithms and iterators — which allow for the traversal and manipulation of container objects.

Is a Function an Algorithm? 

We’ve just established that both functions and algorithms are part of the C++ STL. But what’s the difference between the two? An algorithm is an abstract procedure for solving a specific problem, complete with step-by-step instructions. Algorithms are sometimes likened to cooking recipes: Both can either be recorded in written form, or simply exist in one’s head.

A function in programming, however, is always rendered physically. It’s a piece of code that may implement an algorithm. But not all functions are algorithms: A simple function that accepts an object and writes it to a database can hardly be described as algorithmic. 

Now that we understand how functions differ from algorithms, let’s look at how to write our own function in C++. 

How To Write a C++ Function

Let’s start with a simple C++ function that introduces itself by printing a string to the screen:

#include <iostream>
#include <string>

int introduction() {
std::cout << "I'm a function!\n";
return 0;
}

int main()
{
  introduction();
  return 0;
}

As mentioned earlier, the main() function is part of every C++ program. It’s the interface to all the other functions defined by the program. When we run a C++ script, main() is called automatically and in turn runs all the other functions. Functions invoked by main() need to be defined before the main function itself; otherwise, the compiler throws an error. 

C++ Function Declaration vs. Definition

Let’s now look at our introduction() function. It’s very basic: It simply outputs a short message. Still, its structure is rather interesting. In the first line, the function is declared. A function declaration consists of the function’s return value type, its name and a list of function parameters in brackets. Our function’s list of parameters is empty,  which is just another way of saying that it doesn’t have any.

Forward Declaration

The rest of the function — the part within curly braces — is known as the function body. This is where we define the function. C++ actually allows us to separate a function’s declaration from its definition, in what’s known as “forward declaration.” For longer programs containing a variety of functions, forward declaration helps keep track of the program’s contents. Hence, the following is equivalent to our previous code example: 

int introduction();     // function declaration

int main() {
  introduction();
  return 0;
};

int introduction() {     // function definition
std::cout << "I'm a function!\n";
return 0;
};

C++ Function Return Types

Looking closely through our latest example, you can see that we defined our introduction() function type as int. This means that the function’s return value is an integer — in this case, the digit “0.” However, we don’t use that value once the code is run. So is there a way to get rid of this redundant line of code? Yes, by defining the type of our function as void rather than int,we can omit that last line, for void signals to the compiler that a function has no return value. 

But don’t fall into the trap of defining your main function’s return type as void. While this solution may seem tempting, C++ creator Bjarne Stroustrup has clarified that it goes against the rules of C++. Having main() return “0” isn’t just an aesthetic quirk — it actually serves to signal that the program has successfully run. Even if we don’t explicitly state it in a main function’s definition body, most compilers automatically add the “0” return value.

Return Type Deduction

Other than voids and ints, C++ functions may return all kinds of value types, including strings, characters and tuples. The 2014 C++ language revision introduced an auto return type, which prompts the compiler to itself deduce a function’s type. Now you might be asking if it’s possible to forward-declare a function whose return value is declared as “auto.” The answer is yes — but you’ll have to define the function body before calling it in the main function.

Parameters in C++ Functions

Parameters are placeholders for variables. They’re defined in the brackets behind a function’s name and have local scope (unless defined otherwise). Local scope means that a variable cannot be accessed or manipulated from outside the function. Below, we redefine our introduction function to include a friendly personal greeting:

int introduction(std::string name) {
std::cout << "Hi, " << name <<  "!\nI'm a function!\n";
return 0;
};

int main() {
  introduction("Momo");
  return 0;
};

As you can see, we’ve added a string parameter to our introduction function. Now, when we pass an actual value to a parameterized function, it’s called an “argument.” In the example, we again call our function, this time passing on the name “Momo” as an argument. Here’s the output:

Hi, Momo!
I'm a function!

Call by Value vs. Call by Reference

In the last example, we used the default “call by value” method to pass the name argument to our function. When calling by value, the argument’s value is copied to the function parameter, meaning that changes to the parameter don’t affect the original variable. 

Alternatively, we can pass an argument’s address rather than its value, in what’s known as “call by reference.” With this method, both variables point to the same address in memory. Thus, if the code manipulates the argument in any way, these changes affect our original object. Calling by reference is faster and more efficient than calling by value because it saves the time and space needed to copy an object.

Default Arguments

If your function usually uses the same argument but you still want it to accept alternatives, you may include a default argument in the function’s head:

int introduction(std::string name = "Mimi")

Now, try calling the function without any arguments, and you’ll see that it falls back on using the default argument. If that’s not what you want, you can still pass a different argument to the function, just as we did before.

Functional Programming in C++

If you’ve already ventured into programming territory, you might have come across the concept of functional programming (FP). Functional programming is an old paradigm that has seen renewed interest in past years. Notably, functions in FP are defined in a closer and more mathematically-oriented sense than what we saw above.

In functional programming, a function maps an input (the parameter) to an output (the return value). Crucially, it doesn’t produce any side effects — recall that these are actions that affect data outside of the function. The name can cause confusion for people new to functional programming, since in object-oriented programming, we actually find these effects desirable. 

While C++ is primarily recognized as an object-oriented language, as of 2011, it also supports functional programming. However, while the FP paradigm offers many remedies to various OOP ailments, it requires some rewiring of the object-oriented programmer’s brain. What’s great about C++ is that it supports and encourages different programming paradigms, making it not only a general-purpose but also a multi-paradigm language. 

Tips for Writing Functions in C++

The idea of having functions in the first place was to encourage modular and readable code. But sometimes you might be tempted to define all your code in the main function. In other cases, you might start out with a neat function that does one thing, and continue to modify it until your function’s primary purpose is no longer clear. 

Code is more often read than written. Therefore, keep your functions short and have them accomplish only one task at a time. A good rule of thumb is to always ensure that you can read your entire function when viewing it in a text editor. In his book “The C++ Programming Language,” Bjarne Stroustrup goes even further, recommending an average of seven lines per function.

Just like C (and unlike Python or JavaScript), C++ doesn’t allow for nested functions, i.e. defining a function within a function. While nesting loops is allowed in C++, deep nesting may affect your code’s readability, as well as its speed. It’s often better to keep your code flat and use optimized functions (e.g., the Eigen library for linear algebra operations) instead of nesting. 

Finally, do take the time to think of expressive names for your functions and variables, and if you’re working on larger projects, make sure to document your code. Your collaborators, colleagues and users will all appreciate it!

Become a C++ Developer

C++ is one of the most powerful and versatile programming languages out there. But as the topic of functions shows, it’s certainly not the easiest! Enroll in our online C++ Nanodegree program to master C++ functions, classes and much more.

Start Learning