Неявное преобразование: ссылка на констант против неконфекционной ссылки по сравнению с безреферентом

StackOverflow https://stackoverflow.com/questions/4704404

Вопрос

Рассмотрим этот код,

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 ссылочного совместимого типа.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top