Yahoo Answers is shutting down on May 4th, 2021 (Eastern Time) and beginning April 20th, 2021 (Eastern Time) the Yahoo Answers website will be in read-only mode. There will be no changes to other Yahoo properties or services, or your Yahoo account. You can find more information about the Yahoo Answers shutdown and how to download your data on this help page.

C++: Function pointer ambiguity?

Take the following example. I create a function pointer named "s", set it to f and call it. This compiles fine:

void f() {}

int main() {

    void (*s)();

    s = f;

    s();

}

But take this next example, where I declare "s" now as a reference and set to f inline. This compiles fine as well:

void f() {}

int main() {

    void (&s)() = f;

    s();

}

What is the difference between these two? Specifically the pointer and the reference syntax? I commonly use the former, but the latter seems superfluous? Having to assign s to f inline is the only way it could work in the second one, whereas the with the function "pointer" syntax I had the ability to do it both ways. In terms of usability, what can I do with the second form that I cannot do with the first?

1 Answer

Relevance
  • 9 years ago
    Favorite Answer

    There are really two questions here. They are:

    1. How do you take a pointer to a function, and how do you call a function through a pointer?

    2. What is the difference between a pointer and a reference?

    The answer to question 1 is that you would "normally" write it this way:

      void (*s)();

      s = &f; // This is different from your example.

      (*s)(); // So is this.

    I've marked the two differences from your example. The intuition here is that f is a function, and s is a pointer-to-a-function. Therefore, to take a pointer to f, you write &f, and to obtain the function pointed to by s, you write *s.

    Your version uses two shortcuts provided by C++ (and C, for that matter).

    The first shortcut is that you can abbreviate &f by just f. Why? Basically, because there's no ambiguity. This is very similar to a shortcut you may have used with arrays. If "arr" is an array, then you can write arr to mean a pointer to the first element of arr (that is, &arr[0]).

    The second shortcut is that C++ (and, once again, C) allows you to just write s() instead of (*s)(). The reasoning behind it is pretty much the same as with the first shortcut: there's nothing you can really do with a pointer to a function except call the function pointed to, and so there's no ambiguity here.

    It's useful to know that these are just shortcuts. The "normal" way of taking a pointer to something is to use the & operator, and the "normal" way of dereferencing a pointer is to use the * operator.

    I say "normal", but the fact is that everyone writes it using the shortcuts! However, it does make a difference when you're using pointers to member functions (also known as "methods"), so it pays to keep it straight in your head.

    OK, on to question 2.

    There are two crucial differences between a function and a reference, beyond the obvious syntax differences:

    1. Pointers can be null, but references can't be null.

    2. You can't assign to a reference, you can only initialise it. And it MUST be initialised.

    Point 1 is important to keep in mind, because the C++ implementation doesn't always check that a reference is not null. However, it is, and bad things could happen if it ever is.

    Your compiler will probably reject this:

      void (*ptr)() = 0; // Just fine.

      void (&ref)() = *ptr; // Likely compile error or warning.

    In this situation, the compiler can tell that the reference is null. But in other situations, it may not be able to tell. Just don't do this.

    Point 2 is that this is illegal:

      void (*ptr)() = &f; // Just fine.

      void (&ref)(); // Compile error; references must be initialised

      ref = *ptr; // Compile error; can't assign to a reference

    But this is fine:

      void (*ptr)() = &f;

      void (&ref)() = *ptr; // Reference is initialised

    There's one more difference, which isn't relevant to your situation, but I mention it for completeness: there is such a thing as "pointer arithmetic", but no such thing as "reference arithmetic". If you don't understand this, don't worry; it's probably not important.

Still have questions? Get your answers by asking now.