& после объявления функции в классе

1,00
р.
class A { public: void f() & }
Что означает & после объявления функции?

Ответ
Это означает, что функция может быть вызвана для lvalue объекта класса A.
Рассмотрите следующий пример
#include
class A { public: void f() & { std::cout << "A::f() &" << std::endl } void f() && { std::cout << "A::f() &&" << std::endl } } <br>int main() { A a a.f() A().f() }
Вывод на консоль этой программы
A::f() & A::f() &&
В классе A функция f перегружена для lvale объектов класса A и для rvalue объектов класса A.
В этой программе в предложении
a.f()
вызывается функция f для lvalue объекта a.
В этом же предложении
A().f()
вызывается функция f для rvalue объекта A().
Другой пример.
#include
class A { public: void f() const & { std::cout << "A::f() const &" << std::endl } void f() & { std::cout << "A::f() &" << std::endl } } <br>void h( const A &a ) { a.f() }
int main() { A a a.f()
h( a ) }
Вывод на консоль
A::f() & A::f() const &
В этом примере класс A объявляет две перегруженные функции с именем f: одна для константных lvalue объектов, а другая для неконстантных lvalue объектов.
В предложении
a.f()
вызывается функция для неконстантных объектов, так как объект a не является константным.
Однако внутри функции h
h( a )
вызывается перегруженная функция для константных объектов, так как параметр функции является константой ссылкой.
Еще один пример.
Данная программа не будет компилироваться
#include
class A { public: void f() & { std::cout << "A::f() &" << std::endl } } <br>int main() { A().f() }
Потому что rvalue не может быть привязана к неконстантной ссылке.
Однако если объявить функцию как имеющую дело с константной ссылкой, то программа будет компилироваться
#include
class A { public: void f() const & { std::cout << "A::f() const &" << std::endl } } <br>int main() { A().f() }
Чтобы было более понятно, то можно представить эти функции следующим образом.
Каждая нестатическая функция-член класса имеет неявный параметр, который соответствует this
Поэтому данные две функции-члены класса
void f() const &
и
void f() &
концептуально выглядят как
void f( A * const & ) /*const &*/
и
void f( A * & ) /*&*/
Поэтому последнюю функцию нельзя вызывать для временных объектов типа A *, тогда как первую - можно, так как константная ссылка может привязыватья к временному объекту.
Вот пример, который упрощенно демонстрирует сказанное
#include
void f( int * const & ) { std::cout << "f( int * const & ) " << std::endl } void f( int * & ) { std::cout << "f( int * & )" << std::endl }<br>int main() { int i = 10 int *pi = &i
f( pi ) f( &i ) }
Вывод на консоль:
f( int * & ) f( int * const & )