The "&" denotes a reference instead of a pointer to an object (In your case a constant reference).
The advantage of having a function such as
foo(string const& myname)
over
foo(string const* myname)
is that in the former case you are guaranteed that myname is non-null, since C++ does not allow NULL references. Since you are passing by reference, the object is not copied, just like if you were passing a pointer.
Your second example:
const string &GetMethodName() { ... }
Would allow you to return a constant reference to, for example, a member variable. This is useful if you do not wish a copy to be returned, and again be guaranteed that the value returned is non-null. As an example, the following allows you direct, read-only access:
class A
{
public:
int bar() const {return someValue;}
//Big, expensive to copy class
}
class B
{
public:
A const& getA() { return mA;}
private:
A mA;
}
void someFunction()
{
B b = B();
//Access A, ability to call const functions on A
//No need to check for null, since reference is guaranteed to be valid.
int value = b.getA().bar();
}
You have to of course be careful to not return invalid references.
Compilers will happily compile the following (depending on your warning level and how you treat warnings)
int const& foo()
{
int a;
//This is very bad, returning reference to something on the stack. This will
//crash at runtime.
return a;
}
Basically, it is your responsibility to ensure that whatever you are returning a reference to is actually valid.
It means the member will be invoked when the object is an lvalue reference.
[C++11: 9.3.1/5]:
A non-static member function may be declared with a ref-qualifier (8.3.5); see 13.3.1.
[C++11: 13.3.1/4]:
For non-static member functions, the type of the implicit object parameter is
- “lvalue reference to cv
X
” for functions declared without a ref-qualifier or with the &
ref-qualifier
- “rvalue reference to cv
X
” for functions declared with the &&
ref-qualifier
where X
is the class of which the function is a member and cv is the cv-qualification on the member function declaration. [..]
(and some more rules that I can't find)
Without a ref-qualifier, the function can always be invoked, regardless of the value category of the expression through which you're invoking it:
struct foo
{
void bar() {}
void bar1() & {}
void bar2() && {}
};
int main()
{
foo().bar(); // (always fine)
foo().bar1(); // doesn't compile because bar1() requires an lvalue
foo().bar2();
foo f;
f.bar(); // (always fine)
f.bar1();
f.bar2(); // doesn't compile because bar2() requires an rvalue
}
Live demo (thanks Praetorian)
Best Answer
It's part of a feature allowing C++11 non-static member functions to differentiate between whether they are being called on an lvalues or rvalues.
In the above case, the copy assignment operator being defaulted here can only be called on lvalues. This uses the rules for lvalue and rvalue reference bindings that are well established; this just establishes them for
this
.In the above case, the copy assignment operator is defaulted only if the object being copied into can bind to a non-const lvalue reference. So this is fine:
This is not:
The temporary here cannot bind to an lvalue reference, and thus the copy assignment operator cannot be called. And since this declaration will prevent the creation of the usual copy assignment operator, this syntax effectively prevents copy-assignment (or move-assignment) to temporaries. In order to restore that, you would need to add a
&&
version: