# Chapter 7 - Notes

## Functions&#x20;

* Allows one to compartmentalise and organise a program's execution logic&#x20;
* Can be viewed as a **subprogram** that optionally takes **parameters** and **returns a value**.
* The syntax for defining a function is as follows:

### Function Prototypes&#x20;

A **function prototype** is a **declaration of a function**, in the following syntax:

```
RETURN_TYPE FUNCTION_NAME(PARAMETER_1_TYPE PARAMETER_1_NAME, ...); 
```

* `RETURN_TYPE`: the type of the value returned from the function&#x20;
* `FUNCTION_NAME`: the name of the function that is being declared&#x20;
* `PARAMETER_1_TYPE`: the type of first parameter&#x20;
* `PARAMETER_1_NAME`: the name given for the parameter&#x20;

The number of parameters that a function requires is **optional**, from 0 (no parameters) to 256 parameters.&#x20;

Multiple parameters are specified separated by a comma (`,`).

### Function Definition&#x20;

A **function definition** is the actual meat and potatoes of a function, where the code to be executed is defined.&#x20;

```
RETURN_TYPE FUNCTION_NAME(PARAMETER_1_TYPE PARAMETER_1_NAME, ...) {
    STATEMENT_1;
    STATEMENT_2;
    ...
    return VALUE;
}
```

Much like before, instead of ending the function prototype with a semicolon (`;`) it is followed instead by a statement block (`{...}`).&#x20;

Within the block is the code that will be executed when the function is invoked.&#x20;

### Function Call & Arguments&#x20;

* The code defined as part of a function is not executed unless it is **called/invoked**.
* If the function's definition contains **parameters**, then the function needs to be called with **arguments**.

### Functions Without Return Types&#x20;

* Functions that do not return a value are defined as returning the type `void`.&#x20;
* `return` statements can still be used for such functions on their own (e.g. `return;`)

### Functions Parameters with Default Values&#x20;

**Default parameters** are parameters that **assume a default value** if one is not provided by the function caller. &#x20;

```cpp
void greet(std::string name = "stranger") {
    std::cout << "Hello there, " << name << std::endl;
}

int main() {
    greet("Andrew");  // prints 'Hello there, Andrew'
    greet();  // prints 'Hello there, stranger' 
}
```

## Recursive Functions&#x20;

* **Recursive functions** are functions that calls itself.
* Such functions should have a clearly defined **base case** where it returns without invoking itself again.&#x20;
* The function should get **closer to the base case** with each recursive call.

{% hint style="info" %}
What happens if a recursive function does not have a base case, or the base case never gets executed?&#x20;
{% endhint %}

## Function Overloading&#x20;

Multiple functions can share the same name; what has to be unique is the **function prototype**.

{% hint style="info" %}
What makes up a **function prototype**?&#x20;
{% endhint %}

```cpp
float sum(float a) {
    return a;
}

int sum(int a) {
    return a;
}

int sum(int a, int b) {
    return a + b;
}

int sum(int a, int b, int c) {
    return a + b + c;
}
```

## Arrays as Function Parameters&#x20;

* Array parameters can be specified with the `ELEMENT_TYPE PARAMETER_NAME[]` syntax.

```cpp
void printNumbers(int numbers[], int length); 
```

* The `length` parameter is supposed to denote the length of the array that is passed in, so that you may enumerate over the array without stepping out of bounds.&#x20;

### Array decay&#x20;

Typically we define an array like this:

```cpp
int numbers[10] = {0};
```

This defines a variable called `numbers`, with the type `int[10]` - meaning that the length of the array is embedded into variable type; which is why within the same scope we are able to use a range-based for-loop to enumerate over the array.&#x20;

When creating a function that accepts an array as a parameter, the array is now of the type `int[]`, meaning it has lost information about its size.&#x20;

This is known as **array decay** – the array's type has decayed from one that is **more specific** (`int[10]`) to one that is **less specific** (`int[]`).&#x20;

To circumvent this, we pass in the length of the array as another parameter to the function.&#x20;

## Reference Function Parameters&#x20;

**Reference parameters** allow us to modify the value of an argument from within the function call

This is done by including an ampersand (`&`) after the type of the parameter. &#x20;

```cpp
void foo(int& x) {
    x = 10;
}

int a = 5;
std::cout << a << std::endl; // This prints 5

foo(a);  
std::cout << a << std::endl; // This prints 10
```

This is useful for:

* Emulating multiple return types – using multiple reference variables, we can return more than one value from a function.&#x20;
* Efficiency – if the size of the parameter is large, we can gain some efficiency by passing them by reference.&#x20;
* Changing values – if we need to alter the value of an argument from inside a function&#x20;

## Inline Functions&#x20;

### Preamble

When a function in a program is invoked, there is a couple of 'setup' steps that the program must perform behind the scenes before the code in the function is actually run:&#x20;

* Push all arguments to the stack to be used as parameters&#x20;
* Store the instruction to be executed after the function exits&#x20;
* Jump to the function that is to be executed

And once the code in the function is all run:

* Store the return value of the function&#x20;
* Jump back to the instruction that was previously stored&#x20;

The overhead of this is **usually negligible**, but for a **simple/small function** that will be executed in a **tight loop** this overhead might impact the performance of the program.&#x20;

### Inlining Functions&#x20;

The keyword `inline` when used when defining a function hints to the compiler that the function is to be **expanded inline** whenever it is called.

```cpp
inline double multiply(double a, double b) {
    return a * b;
}

int main() {
    int a, b;
    std::cout << "Enter two numbers: ";
    cin >> a >> b;
    std::cout << "The product is: " << multiply(a, b) << std::endl;
}
```

In the above example, the function `multiply` is expanded inline, and becomes equivalent to:

```cpp
int main() {
    int a, b;
    std::cout << "Enter two numbers: ";
    cin >> a >> b;
    std::cout << "The product is: " << a * b << std::endl;
}
```

{% hint style="info" %}
The `inline` keyword is only a **hint to the compiler** that the function should be inlined if possible. The compiler may choose not to inline your function despite the presence of the keyword.&#x20;

Likewise inlining functions is an optimisation step that your compiler might choose to do **even without the `inline` keyword**.
{% endhint %}

Pros:

* Can improve the performance of your program by avoiding the various overhead of function calls&#x20;
* It increases locality of reference by utilizing instruction cache

Cons:

* Can potentially can code bloat if the inlined function is not small, increasing the executable size&#x20;

When to use:

* When the function is simple & small&#x20;
* When the function is called in a tight loop&#x20;

## Function Pointers

**Function pointers** are a way to assign a function to a variable.&#x20;

At the moment we only use functions as a symbol that we call or invoke; function pointers allow us to perform some logic around the function.&#x20;

```cpp
void SayHelloWorld() {
    std::cout << "Hello world!" << std::endl;
}

int main() {
    auto function = SayHelloWorld;
    function();  // This is the same as `SayHelloWorld()`
}
```

* The `auto` keyword is useful for creating function pointers.&#x20;
* The actual type of a function is `<return_type>(*<variable_name>)(<parameter_type>, <parameter_type>, ...)`
* The declaration `void(*hello_function)()` defines a function variable:
  * called `hello_function`
  * returns a `void` type&#x20;
  * and takes no parameters&#x20;

## Lambda Functions&#x20;

**Lambda functions** give us a way to define a function without actually creating a function.

The syntax for a lambda function is as follows:

```cpp
[ <captures> ] ( <params> ) { <body> }
```

* `<captures>` : refer to variables that exist within the scope where the lambda is defined&#x20;
* `<params>` : refer to any parameters that the lambda function accepts&#x20;
* `<body>` : refers to the body of the lambda function&#x20;
