Почему неконстантный параметр ссылки может быть связан с временным объектом?

char f1();
void f2(char&);

struct A {};

A    f3();
void f4(A&);

int main()
{
f2(f1()); // error C2664. This is as expected.
f4(f3()); // OK! Why???
}

ошибка C2664: ‘void f4 (char &) ‘: невозможно преобразовать аргумент 1 из’ char ‘
чар &’

Меня учили, что в C ++ неконстантный ссылочный параметр не может быть привязан к временному объекту; и в коде выше, f2(f1()); вызывает ошибку, как и ожидалось.

Однако почему это правило не применяется к строке кода f4(f3());?

PS: Мой компилятор VC ++ 2013. Даже если я прокомментирую строку f2(f1());затем код, содержащий f4(f3()); будет скомпилирован без каких-либо ошибок или предупреждений.

Обновить:

MSDN говорит:

В предыдущих выпусках Visual C ++ неконстантные ссылки могли быть
привязан к временным объектам. Теперь временные объекты могут быть связаны только
чтобы констатировать ссылки.

Так что я думаю, что это ошибка VC ++. Я отправил отчет об ошибке Команда VC ++

3

Решение

Если вы компилируете с опция / Za чтобы отключить языковые расширения, компилятор отклоняет оба вызова:

> cl /Za test.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 18.00.21005.1 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

test.cpp
test.cpp(11): error C2664: 'void f2(char &)' : cannot convert argument 1 from 'char' to 'char &'
test.cpp(12): error C2664: 'void f4(A &)' : cannot convert argument 1 from 'A' to 'A &'
A non-const reference may only be bound to an lvalue

Существует несколько (очень ограниченных) обстоятельств, при которых компилятор с включенными языковыми расширениями по-прежнему позволяет неконстантной ссылке lvalue связываться с выражением rvalue. Насколько я понимаю, это в значительной степени позволяет избежать взлома нескольких огромных унаследованных кодовых баз, которые полагаются на это «расширение».

(Как правило, использование / Za не рекомендуется по многим причинам, но в основном из-за того, что заголовки Windows SDK не могут быть # включены с параметром / Za.)

4

Другие решения

Ваш компилятор не соответствует стандарту (может быть, это документированное расширение компилятора?). GCC выдает следующие ошибки:

main.cpp: In function 'int main()':
main.cpp:11:11: error: invalid initialization of non-const reference of type 'char&' from an rvalue of type 'char'
f2(f1()); // error C2664. This is as expected.
^
main.cpp:2:6: error: in passing argument 1 of 'void f2(char&)'
void f2(char&);
^
main.cpp:12:12: error: invalid initialization of non-const reference of type 'A&' from an rvalue of type 'A'
f4(f3()); // OK! Why???
^
main.cpp:7:6: error: in passing argument 1 of 'void f4(A&)'
void f4(A&);
2

По вопросам рекламы [email protected]