views:

2229

answers:

9

Sorry for such a newbie question but there is something I do not quite understand the difference between a C# reference and a pointer. They both point to a place in memory don't they? The only difference I can figure out is that pointers are not as clever, cannot point to anything on the heap, are exempt from garbage collection, and can only reference struts or base types.

One of the reasons I ask is that there is a perception that people need to understand pointers (from C I guess) well to be a good programmer. That a lot of people who leant higher level langauges miss this out and therefore have this weakness.

I just don't get what is so complex about a pointer? It is basically just a reference to a place in memory is it not? Can return it's location, or can be used to interact that the object in that location directly?

So have a missed a massive point?

+10  A: 

C# references can, and will be relocated by garbage collector but normal pointers are static. This is why we use fixed keyword when acquiring a pointer to an array element, to prevent it from getting moved.

EDIT: Conceptually, yes. They are more or less the same.

Mehrdad Afshari
Isn't there another command that prevents a C# reference from having the object it's reference moved by the GC?
Richard
Richard: it's called "fixed"
DrJokepu
Oh sorry, I thought it was something else because the post referred to a pointer.
Richard
Yes, a GCHandle.Alloc, or a Marshal.AllocHGlobal (beyond fixed)
ctacke
It's fixed in C#, pin_ptr in C++/CLI
Mehrdad Afshari
Marshal.AllocHGlobal will not allocate memory in managed heap at all and naturally it's not subject to garbage collection.
Mehrdad Afshari
A: 

start from here: http://msdn.microsoft.com/en-us/library/y31yhkeb.aspx

MarlonRibunal
+1  A: 

Pointers point to a location in the memory address space. References point to a data structure. Data structures all moved all the time (well, not that often, but every now and then) by the garbage collector (for compacting memory space). Also, as you said, data structures without references will get garbage collected after a while.

Also, pointers are only usable in unsafe context.

DrJokepu
A: 

The thing about pointers that makes them somewhat complex is not what they are, but what you can do with them. And when you have a pointer to a pointer to a pointer. That's when it really starts to get fun.

Robert C. Barth
+4  A: 

First I think you need to define a "Pointer" in your sematics. Do you mean the pointer you can create in unsafe code with fixed? Do you mean an IntPtr that you get from maybe a native call or Marshal.AllocHGlobal? Do you mean a GCHandle? The all are essentially the same thing - a representation of a memory address where something is stored - be it a class, a number, a struct, whatever. And for the record, they certainly can be on the heap.

A pointer (all of the above versions) is a fixed item. The GC has no idea what is at that address, and therefore has no ability to manage the memory or life of the object. That means you lose all of the benefits of a garbage collected system. You must manually manage the object memory and you have the potential for leaks.

A reference on the other hand is pretty much a "managed pointer" that the GC knows about. It's still an address of an object, but now the GC knows details of the target, so it can move it around, do compactions, finalize, dispose and all of the other nice stuff a managed environment does.

The major difference, really, is in how and why you would use them. For a vast majority of cases in a managed language, you're going to use an object reference. Pointers become handy for doing interop and the rare need for really fast work.

Edit: In fact here's a good example of when you might use a "pointer" in managed code - in this case it's a GCHandle, but the exact same thing could have been done with AllocHGlobal or by using fixed on a byte array or struct. I tend to prefer the GCHandle becasue it feels more ".NET" to me.

ctacke
+1  A: 

I think it's important for developers to understand the concept of a pointer—that is, to understand indirection. That doesn't mean they necessarily have to use pointers. It's also important to understand that the concept of a reference differs from the concept of pointer, although only subtly, but that the implementation of a reference almost always is a pointer.

That is to say, a variable holding a reference is just a pointer-sized block of memory holding a pointer to the object. However, this variable cannot be used in the same way that a pointer variable can be used. In C# (and C, and C++, ...), a pointer can be indexed like an array, but a reference cannot. In C#, a reference is tracked by the garbage collector, a pointer cannot be. In C++, a pointer can be reassigned, a reference cannot. Syntactically and semantically, pointers and references are quite different, but mechanically, they're the same.

P Daddy
The array thing sounds interesting, is that basically where you can tell the pointer to offset the memory location like an array while you are unable to do this with a reference? Can't think when that would be useful but interesting none the less.
Richard
If p is an int* (a pointer to an int), then (p + 1) is the address identified by p + 4 bytes (the size of an int). And p[1] is the same as *(p + 1) (that is, it "dereferences" the address 4 bytes past p). By contrast, with an array reference (in C#), the [] operator performs a function call.
P Daddy
+5  A: 

A reference is an "abstract" pointer: you can't do arithmetic with a reference and you can't play any low-level tricks with its value.

Chris Conway
+1  A: 

A pointer can point to any byte in the address space of the application. A reference is tightly constrained and controlled and managed by the .NET environment.

jdigital
+2  A: 

There is a slight, yet extremely important, distinction between a pointer and a reference. A pointer points to a place in memory while a reference points to an object in memory. Pointers are not "type safe" in the sense that you cannot guarantee the correctness of the memory they point at.

Take for example the following code

int* p1 = GetAPointer();

This is type safe in the sense that GetAPointer must return a type compatible with int*. Yet there is still no guarantee that *p1 will actually point to an int. It could be a char, double or just a pointer into random memory.

A reference however points to a specific object. Objects can be moved around in memory but the reference cannot be invalidated (unless you use unsafe code). References are much safer in this respect than pointers.

string str = GetAString();

In this case str has one of two state 1) it points to no object and hence is null or 2) it points to a valid string. That's it. The CLR guarantees this to be the case. It cannot and will not for a pointer.

JaredPar
Great explanation.
iTayb