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???
}

error C2664: 'void f4(char &)' : cannot convert argument 1 from 'char' to 'char &'

I have been taught that in C++ a non-const reference parameter cannot be bound to a temporary object; and in the code above, f2(f1()); triggers an error as expected.

However, why does the same rule not apply to the code line f4(f3());?

PS: My compiler is VC++ 2013. Even if I comment the line f2(f1());, then the code containing f4(f3()); will be compiled without any errors or warnings.

Update:

MSDN says:

In previous releases of Visual C++, non-const references could be bound to temporary objects. Now, temporary objects can only be bound to const references.

So I think it is a bug of VC++. I have submitted a bug report to VC++ team

有帮助吗?

解决方案

If you compile with the /Za option to disable language extensions, the compiler rejects both calls:

> 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

There are several (very constrained) circumstances in which the compiler, with language extensions enabled, will still allow a non-const lvalue reference to bind to an rvalue expression. My understanding is that this is largely to avoid breaking several enormous legacy codebases that rely on this "extension."

(In general, use of /Za is not recommended for many reasons, but mostly because the Windows SDK headers cannot be #included with the /Za option.)

其他提示

You compiler is not standard-compliant (maybe this is documented compiler extension?). GCC gives the following errors:

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&);

It appears that the compiler option /permissive- (Configuration Properties > C/C++ > All Options > Conformance Mode) also disables Microsoft language extensions (per James McNellis' answer) and will break non-conforming code.

This option disables permissive behaviors, and sets the /Zc compiler options for strict conformance.

https://docs.microsoft.com/en-us/cpp/build/reference/permissive-standards-conformance?view=msvc-160

For reference I was using Visual Studio 2019 Version 16.9.4 and compiling for the v142 platform toolset.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top