2012-08-11 95 views
5

考虑下面的代码:当未返回未定义对象类型的引用的C++函数的返回值时,会发生什么?

class Foo; 

Foo& CreateFoo(); 


void Bar() 
{ 
    CreateFoo(); 
} 

在Visual Studio中,这将导致错误C2027 foo是一个未定义的类型。在大多数其他编译器中,它编译得很好。如果没有分配CreateFoo的返回值,这只是一个问题。如果我将该行更改为:

Foo& foo = CreateFoo(); 

它在Visual Studio中编译得很好。此外,如果Foo被定义而不是只是前向声明,那么它将在没有赋值的情况下编译好。

哪个应该是正确的行为?在C++标准中有没有解决这个问题的东西,还是这是留给实施的东西?我看了看,没有看到有关这件事的任何内容。

更新: A bug report has been filed.

+0

哪个版本的Visual C++编译器?版本之间的法规遵从性变化很大 – 2012-08-11 01:28:06

+0

这看起来像一个Visual C++编译器错误(我同意Ben Voigt对规范的分析,并且'CreateFoo();'和'Foo&foo = CreateFoo();'之间的行为差​​异很奇怪)。我没有看到这个问题存在一个缺陷,并且它使用Visual C++ 2012重新生成。如果这个问题对您很重要,请考虑在[Microsoft Connect]上打开一个错误(http://connect.microsoft.com/ VisualStudio /)并在此发布链接以供将来参考。谢谢! – 2012-08-11 01:28:24

+0

VS2010提交了一个错误报告,但它被标记为nofix,因为它是一个记录的限制。他们没有提供关于它是否合规的意见。 VS2010中C2027的MSDN页面显示相同类型的问题。 http://msdn.microsoft.com/en-us/library/6c2dk0ah.aspx请参见上一节。它实际上表示不允许对未定义类型的引用,但事实并非如此,它只是在它未被分配返回值时才出现,这在他们的示例代码中就是这种情况。 – Gerald 2012-08-11 01:34:51

回答

6

这看起来像标准的相关部分(第5.2.2节):

函数调用是一个左值如果结果类型是左值引用类型或对函数 类型的右值引用,如果结果类型是对对象类型的右值引用,则为xvalue,否则为prvalue。

如果函数调用是对象类型的prvalue:

  • 如果函数调用或者是

    • 一个decltype说明符的操作数

    • 逗号运算符的右操作数,它是decltype-specifier的操作数

    没有为prvalue引入临时对象。价值的类型可能不完整。 [注意:因此,存储没有分配给prvalue,它不会被破坏;因此,一个类的类型是 没有实例化,作为在这种情况下函数调用的类型的结果。无论 是否表达式使用函数调用符号或运算符表示法(13.3.1.2),情况都是如此。 - 注意:[注意: 不同于decltype说明符的规则,它考虑id表达式是否用括号括起来(7.1.6.2), 括号在此上下文中没有特殊含义。 - 结束注释]

  • 否则,应该完成预估的类型。

由于此函数结果类型为左值引用类型,函数调用的计算结果为一个左值,和完整性的要求并不适用。

该代码是合法的,至少在C++ 11中,没有发布版本的Visual C++完全实现。

+0

谢谢,这是关于我的想法,但不能把它压下。 – Gerald 2012-08-11 01:37:44

1

您可以在函数声明中始终使用不完整的类型(因为它只声明函数的签名,而不是任何实际的代码),但在您使用它时不会使用它。

调用CreateFoo();等于(void) CreateFoo();,我的猜测是Visual Studio需要检查Foo的代码以进行任何转换(我不确定是否可以实际编写无效转换),因为对于转换需要一个完整的类型。

至于Foo & foo = CreateFoo();,这不会做任何转换,所以你可以逃避一个不完整的类型。

+0

谢谢,这对VS为什么不处理它会发光一点。做Foo&foo = CreateFoo(); (空隙)FOO;导致相同的错误。这似乎表明它确实是一个违规问题,因为标准规定:“任何表达式都可以显式转换为cv void类型,在这种情况下,它将成为一个丢弃值表达式”。 – Gerald 2012-08-11 02:14:19