Search

7.8 — Function Pointers

In lesson 6.7 -- Introduction to pointers, you learned that a pointer is a variable that holds the address of another variable. Function pointers are similar, except that instead of pointing to variables, they point to functions!

Consider the following function:

Identifier foo is the function’s name. But what type is the function? Functions have their own l-value function type -- in this case, a function type that returns an integer and takes no parameters. Much like variables, functions live at an assigned address in memory.

When a function is called (via the () operator), execution jumps to the address of the function being called:

At some point in your programming career (if you haven’t already), you’ll probably make a simple mistake:

Instead of calling function foo() and printing the return value, we’ve unintentionally sent function foo directly to std::cout. What happens in this case?

On the author’s machine, this printed:

0x002717f0

…but it may print some other value (e.g. 1) on your machine, depending on how your compiler decides to convert the function pointer to another type for printing. If your machine doesn’t print the function’s address, you may be able to force it to do so by converting the function to a void pointer and printing that:

Just like it is possible to declare a non-constant pointer to a normal variable, it’s also possible to declare a non-constant pointer to a function. In the rest of this lesson, we’ll examine these function pointers and their uses. Function pointers are a fairly advanced topic, and the rest of this lesson can be safely skipped or skimmed by those only looking for C++ basics.

Pointers to functions

The syntax for creating a non-const function pointer is one of the ugliest things you will ever see in C++:

In the above snippet, fcnPtr is a pointer to a function that has no parameters and returns an integer. fcnPtr can point to any function that matches this type.

The parenthesis around *fcnPtr are necessary for precedence reasons, as int *fcnPtr() would be interpreted as a forward declaration for a function named fcnPtr that takes no parameters and returns a pointer to an integer.

To make a const function pointer, the const goes after the asterisk:

If you put the const before the int, then that would indicate the function being pointed to would return a const int.

Assigning a function to a function pointer

Function pointers can be initialized with a function (and non-const function pointers can be assigned a function):

One common mistake is to do this:

This would actually assign the return value from a call to function goo() to fcnPtr, which isn’t what we want. We want fcnPtr to be assigned the address of function goo, not the return value from function goo(). So no parenthesis are needed.

Note that the type (parameters and return type) of the function pointer must match the type of the function. Here are some examples of this:

Unlike fundamental types, C++ will implicitly convert a function into a function pointer if needed (so you don’t need to use the address-of operator (&) to get the function’s address). However, it will not implicitly convert function pointers to void pointers, or vice-versa.

Calling a function using a function pointer

The other primary thing you can do with a function pointer is use it to actually call the function. There are two ways to do this. The first is via explicit dereference:

The second way is via implicit dereference:

As you can see, the implicit dereference method looks just like a normal function call -- which is what you’d expect, since normal function names are pointers to functions anyway! However, some older compilers do not support the implicit dereference method, but all modern compilers should.

One interesting note: Default parameters won’t work for functions called through function pointers. Default parameters are resolved at compile-time (that is, if you don’t supply an argument for a defaulted parameter, the compiler substitutes one in for you when the code is compiled). However, function pointers are resolved at run-time. Consequently, default parameters can not be resolved when making a function call with a function pointer. You’ll explicitly have to pass in values for any defaulted parameters in this case.

Passing functions as arguments to other functions

One of the most useful things to do with function pointers is pass a function as an argument to another function. Functions used as arguments to another function are sometimes called callback functions.

Consider a case where you are writing a function to perform a task (such as sorting an array), but you want the user to be able to define how a particular part of that task will be performed (such as whether the array is sorted in ascending or descending order). Let’s take a closer look at this problem as applied specifically to sorting, as an example that can be generalized to other similar problems.

All sorting algorithms work on a similar concept: the sorting algorithm iterates through a list of numbers, does comparisons on pairs of numbers, and reorders the numbers based on the results of those comparisons. Consequently, by varying the comparison, we can change the way the function sorts without affecting the rest of the sorting code.

Here is our selection sort routine from a previous lesson:

Let’s replace that comparison with a function to do the comparison. Because our comparison function is going to compare two integers and return a boolean value to indicate whether the elements should be swapped, it will look something like this:

And here’s our selection sort routine using the ascending() function to do the comparison:

Now, in order to let the caller decide how the sorting will be done, instead of using our own hard-coded comparison function, we’ll allow the caller to provide their own sorting function! This is done via a function pointer.

Because the caller’s comparison function is going to compare two integers and return a boolean value, a pointer to such a function would look something like this:

So, we’ll allow the caller to pass our sort routine a pointer to their desired comparison function as the third parameter, and then we’ll use the caller’s function to do the comparison.

Here’s a full example of a selection sort that uses a function pointer parameter to do a user-defined comparison, along with an example of how to call it:

This program produces the result:

9 8 7 6 5 4 3 2 1
1 2 3 4 5 6 7 8 9

Is that cool or what? We’ve given the caller the ability to control how our selection sort does its job.

The caller can even define their own “strange” comparison functions:

The above snippet produces the following result:

2 4 6 8 1 3 5 7 9

As you can see, using a function pointer in this context provides a nice way to allow a caller to “hook” their own functionality into something you’ve previously written and tested, which helps facilitate code reuse! Previously, if you wanted to sort one array in descending order and another in ascending order, you’d need multiple version of the sort routine. Now you can have one version that can sort any way the caller desires!

Note: If a function parameter is of a function type, it will be converted to a pointer to the function type. This means

can be equivalently written as:

This only works for function parameters, not stand-alone function pointers, and so is of somewhat limited use.

Providing default functions

If you’re going to allow the caller to pass in a function as a parameter, it can often be useful to provide some standard functions for the caller to use for their convenience. For example, in the selection sort example above, providing the ascending() and descending() function along with the selectionSort() function would make the callers life easier, as they wouldn’t have to rewrite ascending() or descending() every time they want to use them.

You can even set one of these as a default parameter:

In this case, as long as the user calls selectionSort normally (not through a function pointer), the comparisonFcn parameter will default to ascending.

Making function pointers prettier with typedef or type aliases

Let’s face it -- the syntax for pointers to functions is ugly. However, typedefs can be used to make pointers to functions look more like regular variables:

This defines a typedef called “validateFcn” that is a pointer to a function that takes two ints and returns a bool.

Now instead of doing this:

You can do this:

Which reads a lot nicer! However, the syntax to define the typedef itself can be difficult to remember.

In C++11, you can instead use type aliases to create aliases for function pointers types:

This reads more naturally than the equivalent typedef, since the name of the alias and the alias definition are placed on opposite sides of the equals sign.

Using a type alias is identical to using a typedef:

Using std::function in C++11

Introduced in C++11, an alternate method of defining and storing function pointers is to use std::function, which is part of the standard library <functional> header. To define a function pointer using this method, declare a std::function object like so:

As you see, both the return type and parameters go inside angled brackets, with the parameters inside parenthesis. If there are no parameters, the parentheses can be left empty. Although this reads a little more verbosely, it’s also more explicit, as it makes it clear what the return type and parameters expected are (whereas the typedef method obscures them).

Updating our earlier example with std::function:

Type inference for function pointers

Much like the auto keyword can be used to infer the type of normal variables, the auto keyword can also infer the type of a function pointer.

This works exactly like you’d expect, and the syntax is very clean. The downside is, of course, that all of the details about the function’s parameters types and return type are hidden, so it’s easier to make a mistake when making a call with the function, or using its return value. Unfortunately, type inference won’t work for function parameters (even if they have default values), so its use is somewhat limited.

Conclusion

Function pointers are useful primarily when you want to store functions in an array (or other structure), or when you need to pass a function to another function. Because the native syntax to declare function pointers is ugly and error prone, we recommend you use typedefs (or in C++11, std::function).

Quiz time!

1) In this quiz, we’re going to write a version of our basic calculator using function pointers.

1a) Create a short program asking the user for two integer inputs and a mathematical operation (‘+’, ‘-‘, ‘*’, ‘/’). Ensure the user enters a valid operation.

Show Solution

1b) Write functions named add(), subtract(), multiply(), and divide(). These should take two integer parameters and return an integer.

Show Solution

1c) Create a typedef named arithmeticFcn for a pointer to a function that takes two integer parameters and returns an integer.

Show Solution

1d) Write a function named getArithmeticFunction() that takes an operator character and returns the appropriate function as a function pointer.

Show Solution

1e) Modify your main() function to call getArithmeticFunction(). Call the return value from that function with your inputs and print the result.

Show Solution

Here’s the full program:

Show Solution

2) Now let’s modify the program we wrote in quiz 1 to move the logic out of the getArithmeticFcn and into an array.

2a) Create a struct named arithmeticStruct that has two members: a mathematical operator char, and an arithmeticFcn function pointer.

Show Solution

2b) Create a static global array of arithmeticStruct named arithmeticArray, initialized with each of the four arithmetic functions.

Show Solution

2c) Modify getArithmeticFcn to loop through the array and return the appropriate function pointer.

Show Solution

Here’s the full program:

Show Solution

7.9 -- The stack and the heap
Index
7.7 -- Default arguments

397 comments to 7.8 — Function Pointers

  • Barne

    Hi Alex!

    I figured function pointers would be a great fit when making something like an action bar in an MMO, so I decided to try them out in that regard.
    Carefree, I created a class for a player and started sticking in some functions representing spells and created a typedef for a function pointer which was used to create an "actionbar slot", only to discover a whole lot of compiler errors. Many hours of googling and stackoverflow later I found myself using a crappy version looking like this:

    This kind of works, but feels really shoddy. I also could not get the typedef to work in this scenario.
    What I really wanted to do was something like this:

    And I just can't find any answers for this, no matter what I try or search for. It's really a different error no matter the approach. Am I misunderstanding something completely about pointers, or is my syntax just bad? I suspect this has something to do with needing the "this" pointer when dereferencing. Is it a concept I should look at another lesson for? Or is it simply just wrong/bad to implement such a feature in this way?

    If you could take a look at it I would be very grateful.
    Thanks!

    • Barne

      Holy shit, I think I did it! Included a this pointer for the member function pointer.
      Code for review:

      • Yep, you need this this-pointer for member functions. Using `std::function` will save you from the ugly syntax

        If your compiler supports `std::bind_front` (C++20), you can even get around passing `this` when you call the function.

  • Nirbhay

    Hi!

    In the section below, what do you mean by calling the selectionSort 'normally'?

    You can even set one of these as a default parameter:

    In this case, as long as the user calls selectionSort normally (not through a function pointer), the comparisonFcn parameter will default to ascending.

    • Alex

      I mean not through a function pointer. It's a reference back to this part of the tutorial:

      One interesting note: Default parameters won’t work for functions called through function pointers. Default parameters are resolved at compile-time (that is, if you don’t supply an argument for a defaulted parameter, the compiler substitutes one in for you when the code is compiled). However, function pointers are resolved at run-time. Consequently, default parameters can not be resolved when making a function call with a function pointer. You’ll explicitly have to pass in values for any defaulted parameters in this case.

  • Remi Pennington

    this is what I came up with for this project.

    [code]
    #include <iostream>
    #include <functional>

    // define a type the the function pointer return type
    typedef int (*fncptr)(int, int);

    int add(int a, int b) {
        return a + b;
    }
    int subtract(int a, int b) {
        return a - b;
    }
    int multiply(int a, int b) {
        return a * b;
    }
    int divide(int a, int b) {
        return a / b;
    }

    // get input from the user and check to see if the user's input was valid
    void GetInputInt(int &Input) {
        bool fail = false;
        do {
            fail = false;
            std::cin >> Input;
            if (std::cin.fail()) {
                std::cin.ignore(31256, '\n');
                std::cin.clear();
                std::cout << "error: incorrect input please try again: ";
                fail = true;
            }
            std::cin.ignore(31256, '\n');
            std::cin.clear();
        } while (fail);
    std::cout << std::endl;
    }
    // get the operator to use on the two values from GetInputInt
    void GetOperator(char& Operator) {
        bool fail = false;
        do {
            fail = false;
            std::cin >> Operator;
            if (!(Operator == '+' || Operator == '-' || Operator == '*' || Operator == '/')) {
                std::cout << "error: incorrect Input type please try again: ";
                fail = true;
            }
        std::cin.ignore(31256, '\n');
        std::cin.clear();
        } while (fail);
        std::cout << std::endl;
    }
    // return the a pointer to the function denping on the users in put
    fncptr getArithmeticFunction(char op) {
        switch (op) {
        case '+': return add;
            break;
        case '-': return subtract;
            break;
        case '*': return multiply;
            break;
        case '/': return divide;
            break;
            // set to return add my default
        default: return add;
            break;
        }
    }
    int main() {
        //ask the user for two integers
        std::cout << "please two whole numbers\n";
        int num1;
        int num2;
        char Operator;
        //get there inputs
        std::cout << "number 1: ";
        GetInputInt(num1);
        std::cout << "number 2: ";
        GetInputInt(num2);

        //ask the user for an operator
        std::cout << "please enter a an operator: ";
        GetOperator(Operator);

        // declair a pointer to a function denping on the operator
        fncptr ptr = getArithmeticFunction(Operator);
        // declair "result" as the result of the function that the pointers pointing to
        int result = ptr(num1, num2);
        //print the result
        std::cout << "the result is " << result;
        //return 0
        return 0;
    }
    [\code]

    p.s. the [code]...[\code] reminds me a lot of how html works

    • - Use `using` instead of `typedef`, it's easier to read.
      - Inconsistent naming.
      - Initialize your variables with brace initializers.
      - Don't pass magic numbers to `std::cin.ignore`. Pass `std::numeric_limits<std::streamsize>::max()`.
      - Line 27, 32: Duplicate ignore and clear.
      - Inconsistent formatting. Use your editor's auto-formatting feature.
      - If your program prints anything, the last thing it prints should be a line feed ('\n').

      Closing code tags use a forward slash (/).

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    I have an issue!

    My compiler throw an error that sounds:

    • Add another pair of braces

      I explained it here https://www.learncpp.com/cpp-tutorial/78-function-pointers/comment-page-4/#comment-384581

  • Samira Ferdi

    Hi, Alex and Nascardriver!

    > Much like variables, functions live at an assigned address in memory.

    what is assigned to memory address? function's name or what? what about function's body?

    • Functions don't have names after compilation. The function's body is stored as machine code, the place where it is is its address.

      • Samira Ferdi

        So in function foo(), what is foo then? We can access the address of the function using 'foo'. Is foo a variable or something? I'm confuse about 'Functions don't have names after compilation'.

        > The function's body is stored as machine code, the place where it is is its address.
        So, basically you mean that the foo's body store as machine code in foo's address?

        So, up to this point there are 2 kinds of pointer, variable pointer and function pointer. Except the ugly syntax, are there any differences between function pointer and pointer that covered in chapter 6?

        >  Functions have their own l-value function type -- in this case, a function type that returns an integer and takes no parameters

        l-value means variable? So, return type( or return value) and function's parameter are l-value? Parameter in the context of function type, are the number of parameter and their types?

        > int (*fcnPtr)();
        fcnPtr is a variable right? Because according the definition of pointer, fcnPtr must be a variable (but pointing to a function). So, is it means that function's identifier is a variable itself?

        Ah, this lesson is very confusing and overwhelmed!

        • > what is foo then?
          The function's name.

          > I'm confuse about 'Functions don't have names after compilation'.
          Nothing has names after compilation and linkage, unless you explicitly tell the compiler to keep them. Your computer doesn't need names. Focus on understanding the language and worry about how your computer works later.

          > you mean that the foo's body store as machine code in foo's address?
          Yes. Your compiler puts `foo` somewhere, and that's its address. No different than with variables.

          > l-value means variable?
          An l-value is something that can be on the left side of an assignment. That's not entirely right, but works most of the time.

          > return type( or return value) [] are l-value?
          No

          > function's parameter are l-value?
          Yes

          > fcnPtr is a variable right?
          Yes

          > function's identifier is a variable itself?
          No, the identifier is just a name. You can initialize function pointers with functions (without calling the function), because functions are convertible to pointers.

          • Samira Ferdi

            Thank you, Nascardriver for clarify things.

            So, a function pointer is just a (variable) pointer, same with chapter 6, but instead stores variable's address, it stores function's address (or instead of pointing to a variable, it is pointing to a function). It means that function pointer works exactly like pointer that covered in chapter 6 (beside the syntax)?

            Second thing is functions are functions, pointers are pointers but functions are convertible to pointers, right?

            • Yes.
              There are differences though. You can't write to a function pointer. You can use a function pointer as if it was a function (ie. call it).

              • Samira Ferdi

                Thank you, Nascardriver!

                I wanna ask you for clarification. These are the declaration of function things:

                How to make a function that return a function pointer? (I'm confuse with this) Is like this?

                Should myFunctionFoo has same function type with function pointer foo? Or the function that myFunctionFoo returned must has same function type with function pointer foo?

                Pass a function pointer as an argument is passing function by address?

                • > Pass a function pointer as an argument is passing function by address?
                  Yes

                  > Should myFunctionFoo has same function type with function pointer foo?
                  No

                  > the function that myFunctionFoo returned must has same function type with function pointer foo?
                  Yes

                  Or use a type alias to make your code readable.

                  • Samira Ferdi

                    Thanks, Nascardriver!

                    What is this?

                    What is the explanation about constexpr above? I know it's a constant but, it still doesn't make sense for me.

                    • I thought Alex covered `constexpr` functions, but apparently he didn't or I can't find it.
                      Marking a function as `constexpr` suggests the compiler the run the code at compile time if possible.

                      This can greatly reduce the work your program has to do at run-time.

  • Ryan

    Hi~ Thank you for the great lecture!.

    I have a question regarding 2c).

    I kind of trying to use a different way to do 2c, but it keeps causing an error and I don't know how to fix this one.

    Could you tell me how to make this work? or should I just use for each?

    • omfg

      In line 5: "arithmeticArray.op[count]" is "op" an array?
      Try arithmeticArray[count].op, because "airthmeticArray" is the array in this example, not "op".
      The same should go for line 6 airthmeticArray[count].fcn.

    • @omfg is correct.
      Whenever you get an error, please post the full error message with line numbers.

      • Ryan

        Oh, I see. I made the stupid mistake there. How come I didn't see it.  Thank you omfg and nascardriver. I will post the full error message with line numbers as well next time.

  • Anastasia

    After all this lesson wasn't as scary as it seemed, and great quiz as always, thanks!

    Here's my try. Leaving 2 functions returning a function pointer was intentional, I wanted to get used to the original syntax and try both the 'ugly' and the 'pretty' variants. Sorry, if it looks a bit messy because of that (or for other reasons).

    I'm not happy at all with that `return nullptr;` (second_part::getArithmeticFcn() -- Line 124). I don't know what should I do about that, basically I just put it there to get rid of the warning. Can it eventually cause undefined behaviour?

    I don't like much how I handled the 'division by zero' issue either (divide() -- Line 66, 67). I'd leave it be, but since it was triggered by 'nonsense' inputs (e.g. 'fff' for the second operand) as well, I thought I need to do a minimum checking for that.

    And also, I assume whether the arguments are const or not doesn't matter for function pointer as long as the types correspond?

    • - `getOperands`: When you detect a failed extraction, you should try to extract again, not skip to the next variables. An easy way to do this is `--operand` on failed extraction.

      > I don't know what should I do about that [return nullptr]
      Use the same error handling you did before. `std::exit(1)`. Apparently your compiler is smart enough to know that you don't need to return after `std::exit`ing, otherwise the old syntax implementation would've caused a warning too.

      > Can it eventually cause undefined behaviour?
      Yes, when you call a nullptr function in line 140.

      > I don't like much how I handled the 'division by zero' issue
      You could throw an exception (Covered later).

      > I assume whether the arguments are const or not doesn't matter for function pointer
      I never thought about that. Can the pointer even be `const` in the same sense variable pointers are `const`? I don't think function pointer syntax supports this.

      • Anastasia

        Hi, thank you for your response.

        > `getOperands`: When you detect a failed extraction, you should try to extract again, not skip to the next variables. An easy way to do this is `--operand` on failed extraction.
        I didn't want to complicate the function with additional incorrect input handling, since for this quiz it was only important to make sure the operator is correct. `--operand;` is a neat solution though, simple and smart, thank you!

        > Use the same error handling you did before. `std::exit(1)`.
        I was thinking avout exiting there too, but iterating over an array and then exiting with an error seemed like overreacting to me, lol. Somehow it seems more natural to do with switch.

        > I never thought about that. Can the pointer even be `const` in the same sense variable pointers are `const`? I don't think function pointer syntax supports this.
        Now, when you mentioned it, it interests me too. My question was much simpler than that though, I meant just the arguments of the function the pointer points to. For example, in my code above, I used the pointer `int (*)(int, int)` for functions that are `int (*)(const int, const int)` or `int (*)(const int, int)`, so I assumed it doesn't care about that.

        • Marking pass-by-value parameters `const` prevents you from accidentally modifying them inside the function. Those changes don't affect the caller, so this `const` doesn't do a lot.
          Since a non-const or const variables can be passed to a non-const or const parameter (All combinations) by copy, the `const` in the function pointer has no effect.

          • Anastasia

            I know that it doesn't affect the variable itself, I just think that it's a good practice when the return value depends on the passed values being correct and you can also see right away whether the function is supposed to modify the value or not.

            > Since a non-const or const variables can be passed to a non-const or const parameter (All combinations) by copy, the `const` in the function pointer has no effect.
            So, it does make a difference with references and pointers as arguments?

  • Nirbhay

    Hello!

    I understood this lesson almost properly until I came across the Quiz 1 full solution. This is confusing.

    On line 45: typedef int (*arithmeticFcn) (int, int);  means we are replacing 'int' with 'arithmeticFcn' as data type for a function pointer that points to a function that takes two integer parameters. (Ok understood)

    But on Line 65, we use this typedef 'arithmeticFcn' and name a function pointer called 'fcn' which is intitalized with 'getArithmeticFcn(op)'. But as from the definition the function 'fcn' points to should take two integer parameters and not a single char 'op'.

    I think I am missing something here. Please explain in a very simple language.

    Thank you.

    • `getArithmeticFcn(op)` is a function call. The returned pointer is stored in `fcn`.

      • Nirbhay

        Alright.

        1. So to correct myself in the question I asked --

        "typedef int (*arithmeticFcn) (int, int);  means we are replacing 'int (*) (int, int)' with 'arithmeticFcn' as data type for a function pointer that points to a function that takes two integer parameters." - True?

        2. So on line 65, 'arithmeticFcn fcn' is a function pointer which expects
        a pointer to some function that is of type 'int' and takes two integer parameters. So the output of 'getArithmeticFcn(op)' (which is a pointer to add, sub, mul, div functions) is assigned to fcn on line 65?

        Also are "add,subtract, multiply, divide" pointers to the respective functions? just returning "add" means a pointer to the same name function?

        Thanks.

        • > means we are replacing
          Not replacing, just aliasing. The original type still exists. As with all type aliases, using `using` makes this clearer.

          > is assigned to fcn
          `fcn` is initialized with the returned pointer, not assigned. Other than that you're correct.

          > are "add,subtract, multiply, divide" pointers to the respective functions?
          Yes. Using a non-member function without () gives you a pointer to that function. You can clarify your intention by using an ampersand just like you'd do for variables.

  • Mehdi

    What is the syntax for representing functions that takes function pointers as and argument, where that function pointer return another function pointer?

    • Better use type aliases

  • Jan Perme

    Just curious ... in what situations is a function reference a better solution than function pointer ? Are there any rational benefits of using function reference instead of function pointer ? Thanks.

    • Alex

      In the same cases where a reference is better than a pointer -- when null is not a valid option and you can determine which function to reference at the point of initialization. Note that while you can have references to normal functions, you can't have references to member functions.

  • Q

    Why would you ever use the ugly version of the syntax shown here

    For example, I know that the following can be declared this way:

    instead of like this:

    So can't you just declare your example as:

    This is a cleaner syntax than either of your two examples.

    • Alex

      Yes, if a function parameter is a function type, it will be implicitly converted to a pointer to the function type. I added a note about this into the lesson.

      However, I still recommend using type aliases or std::function, as they're cleaner and work in all cases, not just for function parameters.

  • Mehul Malik

    I cant seem to understand this line in the calculator program.This is line number 47

  • Alireza

    Hello,
    thanks for this awesome topic, you've made it very easier to understand.
    Question: What is the pointer to function for my selectionSort(..) function ?

    I tried but I couldn't write it

    And one more:
    What if I want to write a pointer to a function pointer in heap memory ? :D

    • Please don't use @typedef, @using has a more intuitive syntax.
      Function pointer don't support default arguments.

      • Alireza

        Thanks,
        1. Why can't we write a function pointer to @selectionSort(...) like this:

        2. What if we want to set a pointer to a function pointer ?
        3. And what if we want to set a function pointer in heap memory with @new keyword ?

        • 1. You forgot the typedef

          2. I'm not sure what you mean. @selSortPointer is now a pointer type like any other.

          3. You can't (shouldn't) create functions at run-time. If you think you need to do this, please share what you're trying to do.

          • Alireza

            1. I wonder why I should write typedef whereas we set a function pointer(that has another function pointer inside) directly. Maybe I'm wrong or you don't know what I mean ! I'm just curious.

            2. A pointer that points to a function pointer,
            Like we set a pointer to another pointer, how can we do this for function pointers ? Watch below:

            Hope you to figure out it !

            3. OK, let me try.

            I don't know how describe it in other ways, but I've tried !
            If you don't know what I mean, doesn't matter don't think about it.
            Thanks :)

            • 1. This

              is a type. It doesn't do anything on it's own. Either you use it to declare an alias, or you use it to declare a variable.

              The syntax is way off what you'd expect, that's why I'm recommending you to use `using` aliases.

              2. Yes, what you want is independent of the pointer type.

              3. @pf has to point to a function. Functions are created by the compiler. @new allocates memory at run-time. @new can't just make a function appear out of nowhere.
              After you declared @pf, it either has to be a @nullptr, or point to a callable function.

  • Tommy

    Ok, so I can kinda read function pointers, this is really cool, thank you guys!

    One question. I'm still hazy on references and for each loops.
    when you write:

    why is arith a reference and not a struct? Is it simply for memory-saving purposes, ie. to avoid creating a temporary copy of the arithmeticStruct?

    • > why is arith a reference and not a struct?
      Because you put the ampersand there. If you remove the ampersand, it's an instance of @arithmeticStruct.
      Your reasoning to use a reference is correct. Creating copies is slow and unnecessary, the object already exists, so you might as well access it directly.

  • Nguyen

    Hello everyone,

    I almost skipped this lesson when I read " Function pointers are a fairly advanced topic, and the rest of this lesson can be safely skipped or skimmed by those only looking for C++ basics."  I am a slow learner.  So, I was happy to see something like that.  I just tried to see how far I could go.  It turned out this chapter was so helpful and interesting.  The long examples scared me at first....I am so glad I made it thru.  In short, this lesson taught me how to call a function and ask it to return a another function.  If you want to know how a called function returns a another function, this is a great lesson for it.

  • Nguyen

    Hello,

    Making function pointers prettier with typedef or type aliases

    Now instead of doing this:

    You can do this:

    I think the "ugly" should look like as following???

    Thanks

  • Lakshya Malhotra

    Hi,
    First of all, I would like to thank Alex and Nascardriver for these amazing tutorials and equally great forum/comments section.
    Next, I have a question which is more about the best practices and the space-time efficiency of one of the programs that I have already written. After going through these tutorials, I feel like I can still improve my code. So, my question is more of seeking advice from you guys.
    So, I have a C++ code which does Monte-Carlo simulations for like 100 million events. The distribution function I am using is really complicated so I broke it down into simpler functions and variables and defined it as a class in separate class declaration and class implementation files. The actual function which is a function of all those smaller functions and various parameters would look something like this: (this is just the overall skeleton showing what's going on, not the actual code)

    My class declaration file looks something like this:
    "function.h":

    I have defined all these classes' member function and attributes in a separate class implementation file "function.cpp".
    Now, the independent variable in the actual simulation code is coming from a std::vector  which contains all the variables' values for a given range. I am actually looping over the values of variable in a loop along with the function

      
    and all of this is put inside another loop which loops over all the events (100 million in this case).

    I know it would be difficult for you to tell me anything, because this is just a big picture of what's going on. But any feedback would be highly appreciated. Thanks a lot!

    • Hi!

      Just to make sure I understood your loops, you have them set up like this

      Depending on your range, you'll end up with several GiBs of data. If you don't have enough RAM and don't want the OS to swap the memory for you, you can separate the data into blocks and store them in a file. This is especially good for the data you have processed already, as that's just going to sit in memory and do nothing. File IO is covered in chapter 18, you should be able to understand it already.
      Your compiler might not inline @Bar::f_*, meaning that @params has to be passed with every call. You're calling the helper functions n * iNumberOfEvents * range times, so you'll probably notice this in performance. From the looks of it, you can just make @params a member of @Bar and access it directly.
      The next couple of lessons continue to help with performance. Chapter 8 has a lesson about timing your code, you should check that out to help you test code changes.

      I haven't dealt with such large-scale algorithms, someone else might be able to assist you further.

      • Lakshya Malhotra

        Hi,

        Thanks for your prompt reply.  Yes, that's how I set it up.

        I guess my machine has enough hardware resources since the execution time is around 8-10 minutes. But I was just wondering if there is still some scope of improvisation. Because I also tried writing this whole code with pointers and that actually increased the execution time by around 1.5 times which was very surprising for me.

        But yes I can try defining helper functions inline and make @params a member of @Bar.  Also, since there are quite a few helper functions, so my actual

        is getting really cluttered. So should I define @completeFunction in a separate library file which will have access to all the helper functions or my code will suffer a performance penalty? Along with the performance factor, I need to pay attention to the readability of my code since I might have to show my code to others.
        I will also go through the chapters you referred.

        • Can you share the full @completeFunction? I don't know what it looks like.

          • Lakshya Malhotra

            The ones with the prefix "p" before member selector operator belong to class @Foo, "x" is my variable, parameters which do not have member selector operator are basically secondary parameters. The actual class name is DecayFunction. I hope this makes sense.

  • If @op is '-' (A valid operator), the first test (the test for '+'), would be true and the loop would loop around.

  • What is this ftello.

  • Arthur

    tried to give variable / function names to help me remember how it works. need to read on camelCase alternatives so functions and variables are easier to tell apart, and what is standard practice. it was pointed out that I am using the same convention for variables and functions which leads to confusion.

    getOperator makes a void call to errorCorrect which returns a true / false , it works but not sure if that is the way to go about it, I dont know what happens to that return value?

    • Hi Arthur!

      * Line 97: Initialize your variables with brace initializers. You used copy initialization.
      * Line 65: @using has a more intuitive syntax than @typedef.
      * Line 69, 70: Initialize your variables with brace initializers.
      * Line 39, 40: Use switch-statements for limited sets of values. Those allow more compile-time optimizations.
      * @imageToFunctionArray should be @constexpr.
      * Inconsistent formatting. Use auto-format.

      > what is standard practice
      There is no standard practice.

      > need to read on camelCase alternatives
      Hungarian notation, underscores, upper/lower case first letter

      > getOperator makes a void call to errorCorrect
      You should check its return value and @continue the loop if there was an error, as the checks afterwards are unnecessary if an error occurred. Generally there is not problem with ignoring a return value, but it can be an indicator for problematic code.

  • Z_Doctor

    Just tested and the auto keyword works for function pointers (my compiler is at least c++17 compliant: visual studio).

    In other words:

    The code compiled and ran successfully. Also auto can handle if the function has parameters.

  • You need to define @arithmeticFcn before @getArithmeticFcn.

  • nullPointer

    Hi Alex,
    Please help me explain 2 ways assign function pointer!

    and

  • hassan magaji

    hi everyone,
    can i pass a lambda function as an argument to the selection_sort example above?
    if yes -with examples please-
    thank you for these awesome tutorials.

  • Silviu

    Hello,

    Can you explain the callout ? or  guide me to the lesson that helps me to understand. Thank you.
    callback is explained here.

    • Alex

      What callout are you referring to?

      • Silviu

        Sorry for the late answer.
        Callouts from embedded industry.

        We did a lesson between callback vs callout and i did not understand them at that time and i was hopping that i will get some help from here.
        But i managed to understand them.

        (( Callouts are pieces of code that have to be added to the module implementation during
        ECU integration. The content of most callouts is hand-written code.
        In contrast to Callbacks, Callouts are initiated by a module itself.))

        Thank you.

  • Yiu Chung WONG

    I get a linker command failed error when trying to make the operation functions arguments pass by reference. Why is that? thanks.

    Undefined symbols for architecture x86_64:
      "add(int, int)", referenced from:
          getArithmeticFunction(char) in question_1_function_def.o
    ld: symbol(s) not found for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)

    • You didn't update the forward declarations.

      • Yiu Chung WONG

        In hpp file

        In cpp file

        Just realised I also have to update the type definition, which I dislike the syntax.

        Previously

        Also, I find it really annoying that I HAVE to name the function parameters in a forward declarations when I want to pass by reference; but not in pass by value. Is there a reason for this?

        Thank you

Leave a Comment

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