Reputation: 21
so im currently reading sams Teach yourself C++ and am unable to figure out when and why the & operator is used, as it seems like it would be uneccesary in many cases like so:
template <typename objectType>
objectType & GetMax (const objectType & value1, const objectType & value2)
{
if (value1 > value2)
return value1;
else
return value2;
};
Another example:
Template <typename T>
class myTemplateClass
{
public:
void SetVariable (T& newValue) {m_Value = newValue; };
T& GetValue() {return m_Value;};
private:
T m_Value;
};
Please help me understand why &, which I know gets the address of the data type, is here! its definately not making learning the STL any easier.......... THANKS! =)
Upvotes: 2
Views: 120
Reputation: 283624
That's not an operator, and it's not (directly) related to templates.
It's a type modifier, creating (or indicating or denoting or forming) a reference, just like *
creates a pointer.
Much of the time, it's an optimization rather than a necessity. Two Three cases where it is necessary:
In the copy-constructor, it's needed to avoid infinite recursion:
class X
{
//X(X);
// pass by value, the formal parameter is a copy of the actual parameter
// the copy constructor must be called to make the copy
X(const X&); // pass by reference, ok, no copy constructor call necessary
};
Const references in general save having to copy a large object, which is a useful optimization with no surprising behavior.
When the return type of a function, especially operator[]
overload, must appear on the left hand side of an expression:
class Container
{
//Element operator[](int index);
// problematic because c[i] is a temporary
// so c[i] = 5; doesn't actually modify the collection, like it would with an array
Element& operator[](int index); // correct
};
As a similar case, for operators that mutate their left operand, like compound assignment and stream insertion, it's necessary to use a non-const reference parameter.
Any other cases (e.g. output arguments) can (and I think should) be handled with pointers, since a function call that LOOKS like pass-by-value but changes its argument violates the principle of least-surprise. Perfect example: auto_ptr<int> a = new int(5); f(a); /* is a still valid !?! */
Which brings us to case 3, (created because somebody used non-const references outside of operators):
In templates, when the actual type might by auto_ptr
or unique_ptr
, a reference is needed to avoid inferring a type that destroys the original:
auto_ptr<int> a = new int(5);
//template<typename T>
//void dump_target( T handle ) { cout << *item; }
// bad: dump_target(a); destroys *a
template<typename T>
void dump_target( const T& handle ) { cout << *item; } // correct
Upvotes: 8