为什么非const引用参数可以与临时对象绑定?

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

我已经了解到,在C++中,非const引用参数无法绑定到临时对象; 上面的代码 f2(f1()) 会触发预期的错误。
然而,为什么相同的规则不适用于代码行 f4(f3())
PS:我的编译器是VC++2013。 即使我注释掉 f2(f1()) 这一行,包含 f4(f3()) 的代码也会编译而没有任何错误或警告。
更新: MSDN 表示:
以前版本的Visual C ++中,非const引用可以绑定到临时对象。现在,临时对象只能绑定到const引用。

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


你尝试过在代码中不使用f2(f1())来构建吗?这可能会在第一个错误处停止。 - scaryrawr
MSVC 以编译器扩展支持此功能而闻名。不确定 2013 是否支持。 - yngccc
f1() 应该返回一个引用。 - PersianGulf
@xmllmx 只需要在谷歌搜索 msvc const reference temporary 即可。 - yngccc
微软曾经警告过你这个问题,但仍然允许它存在,因为他们的实现没有像大多数编译器那样有效地解除引用。如果他们现在将其标记为明显的错误,那是一件好事,因为这正是标准所要求的。他们在这方面的非标准扩展工作并不有益,因为它促进了不可移植的代码。 - WhozCraig
显示剩余10条评论
3个回答

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

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

(通常不建议使用/Za,原因有很多,但主要是因为Windows SDK头文件不能与/Za选项一起#include。)


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

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接