1

I have two questions

  1. Are both of these declarations of setEvalFunction equivalent for using EvalFunctionPtr = T (*)(const std::vector<T>&);?

    a) void setEvalFunction(const EvalFunctionPtr& evalFunc);
    
    b) void setEvalFunction(T (* const &evalFunc)(const std::vector<T>&));
    
  2. What is the difference between the following parameters (since both seem to work fine).

    a) T (* const &evalFunc)(const std::vector<T>&)
    
    b) T (* const &evalFunc)(const std::vector<T>&)&
    

I want to have something equivalent to 1 a), i.e. passing a reference to a constant function pointer, but without using some extra definition like using EvalFunctionPtr = ....

4
  • Why not using std::function? Commented Oct 29, 2016 at 18:44
  • 1
    I don't think you need to bother with the reference at all. It's const so you can't change it and the cost of passing a function pointer should be the same as passing a reference to a function pointer. Commented Oct 29, 2016 at 18:44
  • I do not use std:function, because it is slower. Passing the value of a function pointer is passing a 64bit integer (in my case of a 64 bit system), which is not the same as passing the reference of a function pointer, since the reference is applied by the compiler, and takes zero time during runtime. But the copy of an integer takes time, doesn't it? Commented Oct 29, 2016 at 19:18
  • @xamid passing a reference doesn't take zero time during runtime. In fact, passing a reference argument to a function is practically copying the (probably 64 bit in your case) address of the pointer and dereferencing it (assuming you actually access the reference), which is more than just copying in the case of passing the pointer by value. If the function was expanded inline by the optimizer, then there is probably no difference either way. Commented Oct 29, 2016 at 20:33

1 Answer 1

1
  1. Are both of these declarations of setEvalFunction equivalent

Yes.

  1. What is the difference between the following parameters (since both seem to work fine).

I do believe that 2. b) R (* const & fptr)(/*args*/)& is ill-formed because a (non-member) function pointer cannot have a ref-qualifier, which is what the final & denotes. However, possibly due to a compiler bug, my GCC does accept it and parses it as same as R (* const & fptr)(/*args*/). EDIT: clang correctly refuses to compile it.

I want to have something equivalent to 1 a), i.e. passing a reference to a constant function pointer, but without using some extra definition like using EvalFunctionPtr = ....

That is quite apt description of 1. b).

Passing the value of a function pointer is passing a 64bit integer (in my case of a 64 bit system), which is not the same as passing the reference of a function pointer, since the reference is applied by the compiler, and takes zero time during runtime. But the copy of an integer takes time, doesn't it?

Passing a reference doesn't take zero time during runtime. In fact, passing a reference argument to a function is practically copying the (probably 64 bit in your case) address of the pointer and dereferencing it (assuming you actually access the reference), which is more than just copying in the case of passing the pointer by value. If the function was expanded inline by the optimizer, then there is probably no difference either way.

Sign up to request clarification or add additional context in comments.

9 Comments

When creating performance tests I get different results. e.g. doing a for loop 10 times, each time doing 10000000 times referencing, copying, and nothing but the for loop (over volatile int), then summing up the timespans gotten by using chrono::steady_clock::now(), i get for example: Overall: 205425 μs taken for reference applies. Overall: 220498 μs taken for copy applies. Overall: 198125 μs taken for for-loop. Overall: 196480 μs taken for reference applies. Overall: 220580 μs taken for copy applies. Overall: 197941 μs taken for for-loop. How can there be such a difference?
I was told about the zero-time performance of references by an assistant at university, who advises the c++ implementation part of my master thesis. I thought I could just trust him, and according to my tests it appears like he was right. However, I do not really find an article stating that.. I case you want my test, you can find it here.
R (* const & fptr)(/*args*/)& is ill-formed, but it isn't attempting to declare a reference to reference. The second & is a ref-qualifier.
@xamid there are a few caveats in your test. 1. You've practically "inline expanded" the imagined function calls explicitly. So, this benchmark is not good for non-inlined functions. If you're only interested in inlined functions, then fair enough. 2. volatile copies cannot be optimized away, unlike non-volatile would be. 3. You don't use the result of the benchmark, so the optimizer can throw the entire loop away - except in the case of volatile copy - which cannot be optimized.
@xamid to slightly fix my previous comment: the entire loop cannot be thrown away because of volatile loop increment, but the unused reference initialization can be. All that you can get out of this benchmark is that references that are both unused and inlined are free :)
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.