Неявное преобразование: ссылка на констант против неконфекционной ссылки по сравнению с безреферентом
-
11-10-2019 - |
Вопрос
Рассмотрим этот код,
struct A {};
struct B { B(const A&) {} };
void f(B)
{
cout << "f()"<<endl;
}
void g(A &a)
{
cout << "g()" <<endl;
f(a); //a is implicitly converted into B.
}
int main()
{
A a;
g(a);
}
Этот компилируется нормально, работает нормально. Но если я изменюсь f(B)
к f(B&)
, Это не компилируется. Анкет Если я напишу f(const B&)
, снова компилируется нормально, работает нормально. Почему причина и обоснование?
Резюме:
void f(B); //okay
void f(B&); //error
void f(const B&); //okay
Я хотел бы услышать причины, обоснование и ссылки из спецификации языка для каждого из этих случаев. Конечно, сами функциональные подписи не являются неправильными. Скорее A
неявно превращается в B
а также const B&
, но не в B&
, и это вызывает ошибку компиляции.
Решение
Я хотел бы услышать причины, обоснование и ссылки из спецификации языка
Является Дизайн и эволюция C ++ достаточный?
Я сделал одну серьезную ошибку, однако, позволив инициализироваться неконфиктической ссылкой не-LVALUE [Комментарий от меня: эта формулировка неточна!] Например:
void incr(int& rr) { ++rr; } void g() { double ss = 1; incr(ss); // note: double passed, int expected // (fixed: error in release 2.0) }
Из -за разницы в типе
int&
не может ссылаться наdouble
прошло так временное, чтобы держатьint
инициализированнымss
Значение. Таким образом,incr()
изменил временный и Результат не был отражен в обратной функции [акцент мой].
Подумайте об этом: весь смысл вызовов за ссылку заключается в том, что клиент передает вещи, которые изменяются функцией, и после возвращения функции, Клиент должен иметь возможность наблюдать за изменениями.
Другие советы
Проблема заключается в том, что неявное преобразование из A в B -объект дает RVALUE. Неконтролируемые ссылки могут связываться только с LVALUES.
Если бы у B был конструктор по умолчанию, вы бы получили такое же поведение, если бы изменили f(a)
позвонить f(B())
.
--
LITB дает отличный ответ на то, что является LVALUE: Переполнение стека - часто используется редко определенные термины: lvalue
GOTW #88: кандидат на «Самый важный констант»
Переполнение стека - почему неконфист не может быть связана с временным объектом?
--
Чтобы объяснить со ссылками на стандарт, как эти вызовы функций не сбои или успешно, было бы чрезмерно длинным. Важно то, как B& b = a;
терпит неудачу const B& b = a;
не терпит неудачу.
(Из проекта N1905)
Ссылка на тип «CV1 T1» инициализируется выражением типа «CV2 T2» следующим образом:
- [является LVALUE и является либо ссылкой, совместимой, либо неявно конвертируемым с LVALUE ссылочного совместимого типа ...]
- В противном случае ссылка должна быть в нелетуальном типе Const (т.е. CV1 должен быть const).
Вот Случай, когда что -то конвертируется в LVALUE ссылочного совместимого типа.