www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - function pointer vs. delegate

reply James Dunne <james.jdunne gmail.com> writes:
Okay, it's been bugging me long enough; I'm just going to swallow my 
pride and ask.

What is the difference between a function pointer and a delegate?

I use function pointers all the time from C and I really enjoy using 
them.  But now C#, D, and other guys come out with delegates, which I 
just assumed were function pointers but renamed.  It seems they are 
slightly more than this.

Can someone clearly lay out the side-by-side differences of these two 
seemingly similar concepts?
Nov 30 2005
next sibling parent David Medlock <noone nowhere.com> writes:
James Dunne wrote:
 Okay, it's been bugging me long enough; I'm just going to swallow my 
 pride and ask.
 
 What is the difference between a function pointer and a delegate?
 
 I use function pointers all the time from C and I really enjoy using 
 them.  But now C#, D, and other guys come out with delegates, which I 
 just assumed were function pointers but renamed.  It seems they are 
 slightly more than this.
 
 Can someone clearly lay out the side-by-side differences of these two 
 seemingly similar concepts?

Function pointers can only access the variables passed to them and declared within(also globals). A delegate can access any variables visible to the enclosing scope. Basically this means a delegate is analagous to a member function whereas a function pointer is just like the C version. Here is an example with an inner function: void foo( int a ) { void bar() { writefln( a ); } call( &bar ); } void call( void delegate() dg ) { dg(); } int main( char[][] args ) { foo( 100 ); } Notice how the bar function has access to the local variable a, even though it was not passed to the function call() ? There is a hidden reference within the delegate to the stack frame inside the call to foo(). Obviously the delegate '&bar' will not be valid once your code exits the foo() function. Hope this helps a bit. -DavidM
Nov 30 2005
prev sibling parent reply Derek Parnell <derek psych.ward> writes:
On Wed, 30 Nov 2005 12:54:09 -0600, James Dunne wrote:

 Okay, it's been bugging me long enough; I'm just going to swallow my 
 pride and ask.
 
 What is the difference between a function pointer and a delegate?
 
 I use function pointers all the time from C and I really enjoy using 
 them.  But now C#, D, and other guys come out with delegates, which I 
 just assumed were function pointers but renamed.  It seems they are 
 slightly more than this.
 
 Can someone clearly lay out the side-by-side differences of these two 
 seemingly similar concepts?

The code inside a delegated function can access variables that are visible at the same scope level as that function. In other words, use delegates if the function is a nested function or inside a class/struct. That way, the function can access variables local to the enclosing function/class/struct. Functions accessed via a function pointer are not passed the 'hidden' reference pointer to the enclosing scope, i.e the stack pointer or 'this'. ===== example ================= import std.stdio; import std.conv; void main(char[][] pArgs) { int hostfunc(int foo) { int nestA(int qwerty) { return (-foo + qwerty); } int nestB(int qwerty) { return (foo - qwerty); } int delegate(int q) n; n = (foo < 0 ? &nestA : &nestB); return n(toInt(pArgs[1])); } for (int x = -6; x < 7; x+=3) { writefln("%d %d", x, hostfunc(x)); } } ===================== f:\temp>build test Path and Version : D:\UTIL\build.exe v2.9(1197) built on Wed Aug 10 11:03:42 2005 f:\dmd\bin\..\..\dm\bin\link.exe test,test.exe,,user32+kernel32,test.def/noi; f:\temp>test 10 -6 16 -3 13 0 -10 3 -7 6 -4 f:\temp>test 100 -6 106 -3 103 0 -100 3 -97 6 -94 -- Derek Parnell Melbourne, Australia 1/12/2005 6:26:10 AM
Nov 30 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
Derek Parnell wrote:
 On Wed, 30 Nov 2005 12:54:09 -0600, James Dunne wrote:
 
 
Okay, it's been bugging me long enough; I'm just going to swallow my 
pride and ask.

What is the difference between a function pointer and a delegate?

I use function pointers all the time from C and I really enjoy using 
them.  But now C#, D, and other guys come out with delegates, which I 
just assumed were function pointers but renamed.  It seems they are 
slightly more than this.

Can someone clearly lay out the side-by-side differences of these two 
seemingly similar concepts?

The code inside a delegated function can access variables that are visible at the same scope level as that function. In other words, use delegates if the function is a nested function or inside a class/struct. That way, the function can access variables local to the enclosing function/class/struct. Functions accessed via a function pointer are not passed the 'hidden' reference pointer to the enclosing scope, i.e the stack pointer or 'this'. ===== example ================= import std.stdio; import std.conv; void main(char[][] pArgs) { int hostfunc(int foo) { int nestA(int qwerty) { return (-foo + qwerty); } int nestB(int qwerty) { return (foo - qwerty); } int delegate(int q) n; n = (foo < 0 ? &nestA : &nestB); return n(toInt(pArgs[1])); } for (int x = -6; x < 7; x+=3) { writefln("%d %d", x, hostfunc(x)); } } ===================== f:\temp>build test Path and Version : D:\UTIL\build.exe v2.9(1197) built on Wed Aug 10 11:03:42 2005 f:\dmd\bin\..\..\dm\bin\link.exe test,test.exe,,user32+kernel32,test.def/noi; f:\temp>test 10 -6 16 -3 13 0 -10 3 -7 6 -4 f:\temp>test 100 -6 106 -3 103 0 -100 3 -97 6 -94

To both Derek and David: Thanks a lot. I figured it was some minute detail like that. Of course, you can simulate the behavior of a delegate using a function pointer that takes a 'this' pointer as the first parameter. I've done this in C++ before; but that was way back before I discovered the member function pointer bass-ackwards syntax. =P I seem to recall a recent post about someone saying that D doesn't have member function pointers... That seems to make more sense now, since a delegate can only access variables local to the CALLER's scope, not the scope in which it was defined. Is this correct?
Nov 30 2005
parent reply Russ Lewis <spamhole-2001-07-16 deming-os.org> writes:
James Dunne wrote:

 Thanks a lot.  I figured it was some minute detail like that.  Of 
 course, you can simulate the behavior of a delegate using a function 
 pointer that takes a 'this' pointer as the first parameter.  I've done 
 this in C++ before; but that was way back before I discovered the member 
 function pointer bass-ackwards syntax. =P
 
 I seem to recall a recent post about someone saying that D doesn't have 
 member function pointers... That seems to make more sense now, since a 
 delegate can only access variables local to the CALLER's scope, not the 
 scope in which it was defined.  Is this correct?

No, the variables it can access are defined at the time of CREATION, not call. I prefer to think of delegates the way that you described them: they are like C function pointers, but with an implicit "this". "this" can point to anything, but it is the creator which decides what it points to. You need to remember that there are two types of delegates: You can build a member function *delegate* by the following: class Foo { char bar(int) {...} } Foo f = new Foo; bar delegate(int) myDelegate = f.bar; The delegate has an implicit pointer to 'f' (actually a pointer to the thing that 'f' is a pointer to), and when you run it, it is exactly the same as running f.bar(...) - it can access any of the variables that bar() can. You can build a delegate literal as well; this has access to any variables that your scope had access to: int baz() { int i,j,k; void delegate() callback = delegate void() { ... }; ... callback(); ... } Think of a delegate literal as a C function pointer where the implicit 'this' is pointing to the stack frame. Delegate literals are often used in D for callbacks; you might pass a delegate literal to some library function, and that library function calls you one or more times to return data to you. Remember that delegate literals become undefined the moment that you leave the stack frame where they were created. So they cannot ever be returned from a function. It's ok, however, to return a delegate which points to a member function. COOL TRICK: Create an object (or struct on the heap), and take a member function delegate to it...then forget the pointer to the object. The implicit 'this' pointer inside the delegate will keep the object alive (prevent garbage collection of it) as long as you store the delegate. I never totally understood C++ member function pointers, but I think that they are a little different than member delegates. With member delegates, what you have is a function pointer to a very specific object; you cannot store a member delegate and expect to be able to execute it on different instances of your class. I think that C++ member function pointers allow for that. In D, you can get most of the same functionality using interfaces.
Dec 01 2005
parent Don Clugston <dac nospam.com.au> writes:
Russ Lewis wrote:
 James Dunne wrote:
 
 Thanks a lot.  I figured it was some minute detail like that.  Of 
 course, you can simulate the behavior of a delegate using a function 
 pointer that takes a 'this' pointer as the first parameter.  I've done 
 this in C++ before; but that was way back before I discovered the 
 member function pointer bass-ackwards syntax. =P

 I seem to recall a recent post about someone saying that D doesn't 
 have member function pointers... That seems to make more sense now, 
 since a delegate can only access variables local to the CALLER's 
 scope, not the scope in which it was defined.  Is this correct?

No, the variables it can access are defined at the time of CREATION, not call. I prefer to think of delegates the way that you described them: they are like C function pointers, but with an implicit "this". "this" can point to anything, but it is the creator which decides what it points to. You need to remember that there are two types of delegates: You can build a member function *delegate* by the following: class Foo { char bar(int) {...} } Foo f = new Foo; bar delegate(int) myDelegate = f.bar; The delegate has an implicit pointer to 'f' (actually a pointer to the thing that 'f' is a pointer to), and when you run it, it is exactly the same as running f.bar(...) - it can access any of the variables that bar() can. You can build a delegate literal as well; this has access to any variables that your scope had access to: int baz() { int i,j,k; void delegate() callback = delegate void() { ... }; ... callback(); ... } Think of a delegate literal as a C function pointer where the implicit 'this' is pointing to the stack frame. Delegate literals are often used in D for callbacks; you might pass a delegate literal to some library function, and that library function calls you one or more times to return data to you. Remember that delegate literals become undefined the moment that you leave the stack frame where they were created. So they cannot ever be returned from a function. It's ok, however, to return a delegate which points to a member function. COOL TRICK: Create an object (or struct on the heap), and take a member function delegate to it...then forget the pointer to the object. The implicit 'this' pointer inside the delegate will keep the object alive (prevent garbage collection of it) as long as you store the delegate. I never totally understood C++ member function pointers, but I think that they are a little different than member delegates. With member delegates, what you have is a function pointer to a very specific object; you cannot store a member delegate and expect to be able to execute it on different instances of your class. I think that C++ member function pointers allow for that.

Nobody fully understands member function pointers. My article: http://www.codeproject.com/cpp/fastdelegate.asp explains just how horrid the C++ situation with member function pointers is. Member function pointers live in a shadowy world between built-in types and user-defined types; they masquerade as pointers, but they're actually undocumented, vendor-specific structs. It's a complete debacle.
 In D, you can get most of the same functionality using interfaces.

Dec 01 2005