c++ – & after a function declaration in a class

Question:

class A
{
public:
    void f() &;
};

What does & mean after a function declaration?

Answer:

This means that the function can be called on an lvalue object of class A .

Consider the following example

#include <iostream>

class A
{
public:
    void f() & { std::cout << "A::f() &" << std::endl; }
    void f() && { std::cout << "A::f() &&" << std::endl; }
};

int main()
{
    A a;
    a.f();
    A().f();
}

Console output of this program

A::f() &
A::f() &&

In class A , the function f is overloaded for lvale objects of class A and for rvalue objects of class A .

In this program, the offer

    a.f();

the function f is called on the lvalue object a .

In the same proposal

    A().f();

function f is called on the rvalue object A() .

Another example.

#include <iostream>

class A
{
public:
    void f() const & { std::cout << "A::f() const &" << std::endl; }
    void f() & { std::cout << "A::f() &" << std::endl; }
};

void h( const A &a )
{
    a.f();
}

int main()
{
    A a;
    a.f();

    h( a );
}

Console output

A::f() &
A::f() const &

In this example, class A declares two overloaded functions named f : one for const lvalue objects and one for non-const lvalue objects.

In a sentence

    a.f();

the function is called for non-const objects, since object a is not const.

However, inside the function h

    h( a );

the overloaded function is called for const objects because the function parameter is a reference constant.

One more example.

This program will not compile

#include <iostream>

class A
{
public:
    void f() & { std::cout << "A::f() &" << std::endl; }
};

int main()
{
    A().f();
}

Because an rvalue cannot be bound to a non-const reference.

However, if you declare a function to deal with a constant reference, then the program will compile

#include <iostream>

class A
{
public:
    void f() const & { std::cout << "A::f() const &" << std::endl; }
};

int main()
{
    A().f();
}

To make it clearer, we can represent these functions as follows.

Every non-static class member function has an implicit parameter that matches this

Therefore, these two member functions of the class

void f() const &

and

void f() &

conceptually look like

void f( A * const & ) /*const &*/

and

void f( A * & ) /*&*/

Therefore, the last function cannot be called on temporary objects of type A * , while the first one can, since a constant reference can bind to a temporary object.

Here is an example that simply demonstrates what has been said

#include <iostream>

void f( int * const  & ) { std::cout << "f( int * const & ) " << std::endl; }
void f( int * & ) { std::cout << "f( int * & )" << std::endl; }

int main()
{
    int i = 10;
    int *pi = &i;

    f( pi );
    f( &i );
}

Console output:

f( int * & )
f( int * const & ) 
Scroll to Top