3
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”转换为“char &”

有人告诉我,在 C++ 中,非常量引用参数不能绑定到临时对象;在上面的代码中,f2(f1());按预期触发错误。

但是,为什么相同的规则不适用于代码行f4(f3());

PS:我的编译器是VC++ 2013。即使我注释了这一行f2(f1());,包含的代码f4(f3());也会被编译,没有任何错误或警告。

更新:

MSDN说:

在以前的 Visual C++ 版本中,非常量引用可以绑定到临时对象。现在,临时对象只能绑定到 const 引用。

所以我认为这是VC++的一个错误。我已向VC++ 团队提交了错误报告

4

2 回答 2

4

如果使用/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

在几种(非常受限的)情况下,启用语言扩展的编译器仍将允许非常量左值引用绑定到右值表达式。我的理解是,这主要是为了避免破坏依赖此“扩展”的几个巨大的遗留代码库。

(一般来说,不推荐使用 /Za 的原因有很多,但主要是因为 Windows SDK 标头不能通过 /Za 选项#included。)

于 2013-10-31T03:19:31.933 回答
2

您的编译器不符合标准(也许这是记录在案的编译器扩展?)。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&);
于 2013-10-31T03:03:18.217 回答