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

Question:

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

What does & mean after a function declaration?

Answer:

This means that the function can be called on the 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 function f overloaded for lvale objects of class A and for rvalue objects of class A

In this program in the sentence

    a.f();

function f is called on the lvalue object a .

In the same sentence

    A().f();

the 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 constant lvalue objects and the other for non-constant lvalue objects.

In a sentence

    a.f();

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

However, inside the function h

    h( a );

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

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 rvalue cannot be bound to a non-const reference.

However, if you declare a function as dealing 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, you can represent these functions as follows.

Each non-static member function of the class has an implicit parameter that corresponds to 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 for temporary objects of type A * , while the first one can be, since a constant reference can bind to a temporary object.

Here is an example that demonstrates the above in a simplified way.

#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