How does a handle differ from a pointer to an object and also why can\'t we have a reference to a reference?
A handle is usually an opaque reference to an object. The type of the handle is unrelated to the element referenced. Consider for example a file descriptor returned by open()
system call. The type is int
but it represents an entry in the open files table. The actual data stored in the table is unrelated to the int
that was returned by open()
freeing the implementation from having to maintain compatibility (i.e. the actual table can be refactored transparently without affecting user code. Handles can only be used by functions in the same library interface, that can remap the handle back to the actual object.
A pointer is the combination of an address in memory and the type of the object that resides in that memory location. The value is the address, the type of the pointer tells the compiler what operations can be performed through that pointer, how to interpret the memory location. Pointers are transparent in that the object referenced has a concrete type that is present from the pointer. Note that in some cases a pointer can serve as a handle (a void*
is fully opaque, a pointer to an empty interface is just as opaque).
References are aliases to an object. That is why you cannot have a reference to a reference: you can have multiple aliases for an object, but you cannot have an alias of an alias. As with pointers references are typed. In some circumstances, references can be implemented by the compiler as pointers that are automatically dereferenced on use, in some other cases the compiler can have references that have no actual storage. The important part is that they are aliases to an object, they must be initialized with an object and cannot be reseated to refer to a different object after they are initialized. Once they are initialized, all uses of the reference are uses of the real object.
A handle
is also sometimes called a "magic cookie". Its just a value of some opaque type that identifies an object. In some cases it's implemented as an actual pointer, so if you cast it to a pointer to the correct type, you can dereference it and work with whatever sort of thing it points at.
In other cases, it'll be implemented as something other than a pointer -- for example, you might have a table of objects of that type, and the handle is really just an index into that table. Unless you know the base address of the table, you can't do much of anything with the index.
C++ simply says that references to references aren't possible. There isn't much in the way of a "why" -- if they'd wanted to badly enough, they undoubtedly could have allowed it (as well as arrays of references, for that matter). The decision was made, however, that it was best to restrict references (a lot), so that's what they did.
To even ask the question, "why can't we have a reference to a reference?" means you don't understand what a reference is.
A reference is another name for an object; nothing more. If I have an object stored in variable X, I can create a variable Y that is a reference to this object. They're both talking about the same object, so what exactly would it mean to have a reference to Y? It wouldn't be any different from having a reference to X because they're all referencing the same thing.
A "handle" does not have a definition as far as the C++ language is concerned. Generally speaking, a "handle" is a construct of some form which represents some sort of resource. You get it from some API that creates the resource. You call functions that take the handle as a parameter in order to query the state of the resource or modify it. And when you're done with it, you give it to some other API function.
A pointer could be a handle. A reference could be a handle. An object could be a handle. An integer could be a handle. It all depends on what the system that implements the handle wants to do with it.
The difference is the context.
Basic meaning of a handle is that it refers to some object in very limited context; eg. an OS can keep only 20 files opened for a user or pid. A pointer refers to the same object in the context of "memory". And reference is an "alias" to an object -- it refers to an object in the context of source code; thus reference to a reference doesn't exists as a reference already "is" the object.