Beginner's Guide
    First Steps
    Input & Output
    Custom Types – Part 1
    Diagnostics
    Standard Library – Part 1
    Function Objects
    Standard Library – Part 2
    Code Organization
    Custom Types – Part 2
    Generic Programming
    Memory Management
    Software Design Basics

    Functions (Basics) Functions (Basics) Functions

    Inputs & Outputs In/Out

    First Example Example

    double mean (double a, double b) {
      return (a + b) / 2;
    }
    
    int main () { std::cout << mean(2, 6) <<'\n'; // prints 4 }
    • encapsulation of implementation details
    • easier reasoning about correctness and testing by breaking down problems into separate functions
    • avoids repeating code for common tasks
    function-related terminology
    // "call" at "call site"
    auto result = name(argument1, argument2);
    // "call" at "call site"
    auto result = name(argument1, argument2);

    Return Types

    Full Return Type Deduction   C++14 (deduction = compiler determines type automatically)
    auto foo (int i, double d) {
      
      return i;
    }
    //  OK: return type: int
    auto foo (int i, double d) {
      return i;  //  int
      
      return d;  //  double
    } 
    //  ERROR: Inconsistent return types!

    Parameters

    • none: f()
    • one or many: g(int a, double b, int c, …)
    • parameter names have to be unique within list

    const Parameters const

    int foo (int a, int const b) {
      a += 5;   // 
      b += 10;  //  COMPILER ERROR: can't modify const parameter
      return (a + b);
    }
    
    // calling foo: foo(2,9); // const has no effect here

    Any 2nd argument passed to foo will be copied into the local variable b ⇒ the fact that b is const has no effect outside of foo.

    If you don't need or must not change values of parameters inside the function then make them const!

    Defaulted Parameters Defaults

    double f (double a, double b = 1.5) {
      return (a * b);
    }
    int main () {
      cout <<  f(2);     // 1 argument  → 3.0
      cout <<  f(2, 3);  // 2 arguments → 6.0
    }
    
    void foo (int i = 0); void foo (int n, double x = 2.5); void foo (int a, int b = 1, float c = 3.5f);
    void foo (int a, int b = 1, int c );
    Each parameter after first default must have default value, too!

    Overloading

    • functions with the same name but different parameter lists
    • cannot overload on return type alone

    Implementation

    Recursion

    = function calling itself
    • needs a break condition
    • looks more elegant than loops but in many cases slower
    • recursion depth is limited (by stack size)
    int factorial (int n) {
        // break condition:
        if (n < 2) return 1;  
        // recursive call: n! = n * (n-1)!
        return (n * factorial(n - 1));  
    }

    Declaration vs. Definition Declaration

    • can only call functions that are already known (from before/above)
    • only one definition allowed per source file (translation unit)
    • ok to have any number of declarations = announcing the existence of a function by specifying its signature
    Example: Broken! (click!)
     COMPILER ERROR: - 'odd'/'even' not known before 'main'!
     COMPILER ERROR: - 'odd' not known before 'even'!
    
    int main () { int i = 0; cin >> i; if (odd(i)) cout << "is odd\n"; if (even(i)) cout << "is even\n"; }
    bool even (int n) { return !odd(n); }
    bool odd (int n) { return (n % 2); }
    Working (click!)
    bool even (int);  // declaration
    bool odd (int);   // declaration
    
    int main () { // definition int i = 0; cin >> i; if (odd(i)) cout << "is odd\n"; // OK, already declared if (even(i)) cout << "is even\n"; // OK, already declared }
    bool even (int n) { // definition return !odd(n); // OK, already declared }
    bool odd (int n) { // definition return (n % 2); }

    Design

    Interfaces should be easy to use correctly and hard to use incorrectly.
     —  Scott Meyers

    Contracts

    • Preconditions: What do you expect/demand from input values?
    • Postconditions: What guarantees should you give regarding output values?
    • Invariants: What do callers/users of your function expect to not change?
    • Purpose: Has your function a clearly defined purpose?
    • Name: Does the function's name reflect its purpose?
    • Parameters: Can a caller/user easily confuse their meaning?

    overview of function contract terminology: preconditions, postconditions, invariants, side effects

    Wide Contract Functions perform precondition checks, i.e., check input parameter values (or program state) for validity

    Narrow Contract Functions do not perform precondition checks, i.e., the caller has to make sure that input arguments (and program state) are valid

    Attribute [[nodiscard]] [[nodiscard]] [[nodiscard]] C++17

    [[nodiscard]] bool prime (int i) {  }
    // return value(s) used:
    bool const yes = prime(47);
    if (prime(47)) {  }
    // return value discarded/ignored:
    prime(47);  //  COMPILER WARNING

    std::vector's empty() function is declared with [[nodiscard]] as of C++20, because it can be confused with clear():

    std::vector<int> v;
    // 
    if (v.empty()) {  }  // OK
    v.empty();  // C++20:  COMPILER WARNING
    // oops … did someone meant to clear it?
    • if calling it without using the return value makes no sense in any situation
    • if users could be confused about its purpose, if the return value is ignored

    No-Throw Guarantee: noexcept noexcept noexcept C++11

    C++ has a mechanism for reporting errors using exceptions like many/most other programming languages. Don't worry, if you don't know what exceptions are, they will be explained in a later chapter.

    The noexcept keyword specifies that a function promises to never throw exceptions / let exceptions escape:

    void foo () noexcept { … }

    If an exception escapes from a noexcept function anyway, the program will be aborted.

    Some Mathematical Functions Mathematical Functions Math

    #include <cmath>
    double sqrt (double x) √x square root
    double pow (double a, double b) ab power
    double abs (double x) |x| absolute value
    double sin (double x) sin(x) sine
    double cos (double x) cos(x) cosine
    double exp (double x) ex exponential
    double log (double x) log(x) logarithm
    double floor (double x) ⌊x⌋ next smaller integer
    double ceil (double x) ⌈x⌉ next larger integer
    double fmod (double x, double y) remainder of x/y