繁体   English   中英

通过指针转换将rvalue绑定到非const引用?

[英]Binding rvalue to non-const reference via pointer cast?

我不明白以下代码如何编译/不编译:

struct Temp
{
  int i;
};

int main(int argc, char * argv[])
{
   //Temp &ref1 = (Temp){42}; // Error, as expected
   Temp &ref2 = *(Temp*)&(Temp){42}; // A-OK
   std::cerr << ref2.i << std::endl;
   return 0;
}

我正在使用g ++ 4.4.4。

你的代码不是真正的C ++。 它使用复合文字,这是一个C99功能。 在C99中,它评估为左值,并且在那里获取文字的地址是完全正确的。 将此扩展集成到C ++中,GCC似乎改变了它的规则并使其成为右值,更适合将它们分类为现有的C ++规则,以便生成rvalues。

海湾合作委员会不喜欢&(Temp){42} ,抱怨我拿一个临时的地址。 这是一个关于无效代码的警告,它仍然接受但并不喜欢。 对于其他明显错误的代码,如&A()也给出了相同的警告,这是一个合法的函数式C ++转换,它也产生一个rvalue,因此不能用作address-of运算符的操作数。

GCC将复合文字整合到C ++中也会过早地破坏临时性,如下面的测试所示

#include <iostream>
struct B {
  ~B() {
    std::cout << "~B" << std::endl;
  }
};
struct A { int i; B b; };

int main() {
  A *a = &(A){0};
  std::cout << "main" << std::endl;
}

在C99中,文字引用的对象将在整个块中处于活动状态(它将具有自动存储持续时间)。 在GNU C ++中,对象在完整表达式结束时已被破坏,甚至在其块结束之前(“〜”打印在“main”之前)。

我可能会对此有所误解,但这看起来像是编译器中的一个错误。 C ++ ISO标准§5.3.1/ 2将&运算符视为

一元&运算符的结果是指向其操作数的指针。 操作数应为左值或限定ID。

§5.4/ 1节讨论了铸造操作员

表达式(T) cast-expression的结果T型。 如果T是引用类型, 结果是左值, 否则结果是右值。

这似乎表明了这一点

(Temp){42}

产生一个右值,你不应该在法律上允许你使用&的地址。

我之前已经知道在阅读规范时犯了错误,所以如果有人能证实这一点会很棒。

正如templatetypedef所说,它似乎是编译器中的一个错误。 使用4.6.0版本的GCC编译时,它给出:

error: taking address of temporary [-fpermissive]

而且,当然,通过添加-fpermissive,它会编译但是抱怨,但它仍然不会崩溃并打印出正确的结果。 我猜GCC在“宽容”条件下有点作弊。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM