Why? Because, although consistent terminology is generally good for the entire profession, language designers don't always respect the language use of other language designers, particularly if those other languages are perceived as competitors.
But really, neither use of 'reference' was a very good choice. "References" in C++ are simply a language construct to introduce aliases (alternative names for exactly the same entity) explicitly. Things would have been much clearer of they had simply called the new feature "aliases" in the first place. However, at that time the big difficulty was to make everyone understand the difference between pointers (which require dereferencing) and references (which don't), so the important thing was that it was called something other than "pointer", and not so much specifically what term to use.
Java doesn't have pointers, and is proud of it, so using "pointer" as a term was no option. However, the "references" that it does have behave quite a bit as C++'s pointers do when you pass them around - the big difference is that you can't do the nastier low-level operations (casting, adding...) on them, but they result in exactly the same semantics when you pass around handles to entities that are identical vs. entities that merely happen to be equal. Unfortunately, the term "pointer" carries so many negative low-level associations that it's unlikely ever to be accepted by the Java community.
The result is that both languages use the same vague term for two rather different things, both of which might profit from a more specific name, but neither of which is likely to be replaced any time soon. Natural language, too, can be frustrating sometimes!
Firstly, you probably shouldn't implement a container class. 95% of the time you should one included in the standard library. If you just want to learn, or are in the 5%, carry on.
If you are defining a template, leave the decision up to your users. You users can use:
Stack<Foo>
if they want by value.
Stack<Foo*>
if they want by pointer.
Stack<std::unique_ptr<Foo>>
if they want pointers that clean up after themselves.
When choosing which to use, you should default to by value, unless you've got a good reason to do something different. Inside your stack class, just store everything by value. If the use of the template needs indirection, they can use T=pointer type.
Looking at your code:
void push(const T& item) {
if(size == capacity - 1)
enlargeArray();
data[indexToInsert++] = &item;
size++;
}
You can't do that. &item
records the pointer to whatever was passed in. But you have no idea how long the pointer will be valid for. It could become invalid right after push finished. In that case, you've stored a pointer to an invalid place. In general, you can't assume that a pointer remains valid. You should instead be copying the item.
Best Answer
To start off, your code is broken. Returning a reference or the address of a local variable is returning garbage. Never do this. Here I've rewritten your example to return something real.
In this example,
xByReference
is assigned the value 23.xByAddress
is assigned the value 245. Of course,returnByAddress() = &x;
is invalid.The rule is: functions return rvalues. The only way around this is to return a reference.
returnByAddress()
returns a pointer by rvalue. You can deference the pointer to get an lvalue of the thing pointed at.Following this rule, you can return a reference to the pointer.
This code changes
xPointer
to point at the address ofx
.