Каковы свойства категории значений функций-членов в C ++ 11? - PullRequest
0 голосов
/ 16 марта 2019

Читая о категориях значений в C ++ 11 и далее на cppreference , мне трудно понять мотивацию для того, чтобы функции-члены были prvalues.

a.m,член выражения объекта, где m является ... нестатической функцией-членом

За исключением того, что они не являются истинными значениями, потому что их единственное свойство заключается в том, что они могут быть вызваны.

Выражения a.mf ... [и друзья] ... классифицируются как выражения prvalue, но их вообще нельзя использовать ... для каких-либо целей, кроме как в качестве левого аргументаоператор вызова функции

Кроме того, как временная материализация C ++ 17 взаимодействует с категорией значений функций-членов?Начиная с cppreference ,

Временная материализация происходит ... при выполнении доступа члена к классу prvalue

Для меня это имеет больше смысла в целомчто функции являются неизменяемыми l-значениями.То есть у них есть определенное местоположение.Я понимаю, что в случае виртуальной функции-члена нет местоположения времени компиляции, поэтому я понимаю, почему этот случай не будет lvalue.Я также вижу, что функция-член временно материализованного класса также может не иметь местоположения времени компиляции и не может быть lvalue, хотя функция-член все еще где-то компилируется и имеет местоположение (C ++ может просто сделать невозможным обращение к этому местоположению вуровень языка).

Что меня больше всего смущает, так это то, что компилятор в конечном итоге не будет относиться к не виртуальной функции-члену иначе, чем к любой другой функции.Единственная разница - искажение имени.Так почему же в мире они относятся к разным категориям значений?

Должна быть веская причина, по которой функции-члены не являются lvalues, если они имеют четко определенное местоположение.Это настоящая мутная вода.Может ли кто-нибудь дать мотивацию и разъяснение?

Ответы [ 2 ]

1 голос
/ 16 марта 2019

Нестатические функции-члены не имеют "четко определенное местоположение". «Местоположение» виртуальной функции-члена неизвестно (вообще) во время компиляции. И даже игнорируя это, «расположение» функций-членов никогда не обрабатывается в C ++.

Да, существуют "указатели на функции-члены", но обратите внимание, что эти типы не могут быть преобразованы в указатели на другие вещи. Стандарт даже не позволяет реализациям разрешать преобразование в целые числа и обратно через reinterpret_cast, как это делается для обычных указателей. Они не являются «указателями» в смысле адресов памяти.

Функции-члены не имеют местоположений в том же смысле, что и другие вещи C ++. Поэтому классифицировать их как prvalues ​​имеет смысл.

Кроме того, как временная материализация C ++ 17 взаимодействует с категорией значений функций-членов?

Временная материализация применяется к объектам ; функция-член не является объектом. Обратите внимание на то, что вы цитируете: «при выполнении доступа члена к классу prvalue ». Функции-члены не являются классами, поэтому они не применяются.

Что меня больше всего смущает, так это то, что компилятор в конечном итоге не будет относиться к не виртуальной функции-члену иначе, чем к любой другой функции.

То, как компилятор реализует стандарт, не имеет значения. Стандарт объявляет их как значения, так что они такие.

0 голосов
/ 16 марта 2019

После недолгого размышления становится очевидным, почему функции-члены как lvalues ​​будут абсурдными. Любая функция-член имеет параметр неявного аргумента this, который абстрагируется от уровня языка C ++. В результате lvalue для функции-члена не будет иметь никакого контекста для this, и это будет бесполезно, поскольку не будет никакого способа вызвать его.

Кроме того, виртуальные классы имеют дополнительный скрытый элемент виртуального указателя. Виртуальные функции-члены уже не могут быть lvalues, потому что они нерешительны во время компиляции, но виртуальный член-указатель также будет потерян, потому что он извлекается из this, поэтому это вторая причина, по которой виртуальная функция-член не может быть именующие.

Я считаю это ошибкой в ​​дизайне C ++, а дублирование функций-членов как "prvalues" - грубое прикрытие. Если бы не было скрытых параметров, то функции-члены были бы lvalues ​​(могут вызываться путем передачи ссылки на объект). Кроме того, если бы не было скрытых членов класса, и если виртуальная таблица не была скрыта, то виртуальная таблица могла бы быть запрошена для получения l-значений для виртуальных функций во время выполнения (в настоящее время это вообще невозможно в C ++). Конечно, тогда будет определена реализация виртуальных функций, но это не плохая, не редкая и не беспрецедентная вещь, если учесть, что RVO и разрешение копирования существуют.

...