C ++临时和构造函数

时间:2013-01-05 07:38:53

标签: c++

为什么有些编译器抱怨从构造函数中获取临时地址而某些编译器没有?

例如:

WriteLine(&String8("Exception"));

我假设抱怨的编译器没有将该地址存储在堆栈中,如果我忽略该警告,它将会爆炸。有没有办法让它在一条线上工作?是返回地址的类的静态方法的最佳/唯一方法吗?嗯我不认为返回指针的String8类上的静态方法可以工作,因为它会将String8类保存到寄存器然后在WriteLine()中使用它

2 个答案:

答案 0 :(得分:5)

您提供的示例代码,

WriteLine(&String8("Exception"));

无效作为标准C ++,除非String8类型定义了自定义地址运算符。


你问,

  

“为什么有些编译器会抱怨从构造函数中获取临时地址而某些编译器不会?”

有些编译器抱怨说,因为C ++标准说你不能使用内置地址运算符来获取临时地址:

  

C ++11§5.3.1/ 3
  “一元&运算符的结果是指向其操作数的指针。操作数应为左值或 qualified-id 。“

某些编译器(如Visual C ++)不会抱怨,因为它们可以将地址作为语言扩展


请注意,用户定义的类型可以定义自定义地址运算符。因此,在您的情况下,取决于String8类型。以及编译器。


你进一步问,

  

“有没有办法让它在一条线上工作?”

是的,可以定义地址运算符。但这不是一个好主意。首先,它只会产生标准库等问题,其次,对此的需求非常少见。

我只记得一个我认真考虑过这种解决方案的案例,即将COM智能指针作为out-argument传递。我没有定义地址运算符,而是定义了一个命名方法。它更加清晰,不会干扰其他事情。

答案 1 :(得分:2)

代码完全有效( on MSVC )。你可以把这个警告当作红鲱鱼。

有两个问题需要考虑:

  1. 取一个临时的地址( a.k.a:rvalue ),这是根据标准&
  2. 不允许的
  3. 临时居民的终身时间。
  4. 反击问题1:
    MSVC允许您通过扩展名获取临时地址。因此,获取临时的地址将至少在您的情况下编译(MSVC提供)。

    反击问题2:
    此外,临时String8("Exception")保证至少在表达式结束之前存在。请注意,表达式在从WriteLine()返回后结束,确切地说是;在调用结束时的分号)。所以它完全有效。在这种情况下,您可以将警告视为红鲱鱼。

    C ++ 03标准§12.2/ 3:

      

    临时对象作为评估全表达式(1.9)的最后一步被销毁,该表达式(词法上)包含创建它们的点。