Указатель на участника, который является незаконной ссылкой?
Допустим, у меня есть:
// This is all valid in C++11.
struct Foo {
int i = 42;
int& j = i;
};
// Let's take a pointer to the member "j".
auto b = &Foo::j; // Compiler is not happy here
// Note that if I tried to get a pointer to member "i", it would work, as expected.
Foo f;
std::cout << f.*b; // Try using the pointer to member
Компилятор жалуется, что я не могу взять адрес участника, потому что это ссылка. Точнее:
Семантическая проблема: невозможно сформировать указатель на член для элемента 'j' ссылочного типа 'int &'
Я знаю, что делать это кажется бессмысленным, но мне только интересно, почему это невозможно сделать.
Почему это невозможно?
4 ответа
Указатель элемента (в отличие от простого указателя на элемент) - это просто смещение в структуре, а не указатель вообще. Через него можно получить данные только в сочетании с самой структурой (или указателем на структуру): значение смещения добавляется к адресу структуры, а результат разыменовывается для получения значения элемента.
Теперь предположим, что член является ссылкой, поэтому доступ к данным через него уже требует разыменования (компилятор скрывает это от нас, но ему нужно выложить соответствующие инструкции в свои выходные данные). Если бы C++ позволял указателям на ссылки на элементы указывать, они были бы другого типа: смещение, которое нужно добавить в базу, а затем дважды разыменовать. Это слишком много работы, чтобы улучшить и без того неясную функцию; Запретить это гораздо лучший выход.
Это невозможно сделать, потому что вы не можете взять указатель на ссылочный период.
Если бы вы могли взять указатель члена на ссылку, это было бы несовместимо с поведением ссылок в стеке. Отношение C++ заключается в том, что ссылки не существуют. Таким образом, вы не можете сформировать указатель на них.
Например, &f::a
будет отличаться от &f::b
, И путем разыменования &f::b
, вы бы эффективно получили указатель на ссылку, что недопустимо.
Стандарт C++11:
§8.3.3 p3 [dcl.mptr]
Указатель на член не должен указывать на статический член класса (9.4), член со ссылочным типом или "cv void".
Также в общем:
§8.3.1 p4 [dcl.ptr]
[Примечание: нет указателей на ссылки; см. 8.3.2. [...] - конец примечания]§8.3.2 p5 [dcl.ref]
Не должно быть ссылок на ссылки, массивов ссылок и указателей на ссылки.
Разрешение сделать указатель на ссылку не дает вам никакой выразительной силы. Вы ничего не можете сделать с таким зверем, которого вы не можете легко сделать с помощью ссылки или указателя. Все, что вы получаете от этого, это сложность.
И создание указателя на член, который является ссылкой, недопустимо для соответствия правилу, которое запрещает указатели на ссылки, и потому что это добавляет еще большую сложность. Разработчики языка, вероятно, решили, что небольшие выгоды, которые вы получите от них, не стоили того.
Это полностью мое мнение.