Страницы

Поиск по вопросам

вторник, 2 октября 2018 г.

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

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; } };
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; } };
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; } };
int main() { A().f(); }
Потому что rvalue не может быть привязана к неконстантной ссылке.
Однако если объявить функцию как имеющую дело с константной ссылкой, то программа будет компилироваться
#include
class A { public: void f() const & { std::cout << "A::f() const &" << std::endl; } };
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; }
int main() { int i = 10; int *pi = &i;
f( pi ); f( &i ); }
Вывод на консоль:
f( int * & ) f( int * const & )

Комментариев нет:

Отправить комментарий