2

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

例如:

WriteLine(&String8("Exception"));

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

4

2 回答 2

5

您提供的示例代码,

WriteLine(&String8("Exception"));

与标准 C++ 一样无效,除非该String8类型定义了自定义地址运算符。


你问,

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

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

C++11 §5.3.1/3
“一元运算符的结果&是指向其操作数的指针。操作数应该是一个左值或一个合格的 id。”

一些编译器,例如 Visual C++,不会抱怨,因为它们提供了将地址作为语言扩展的能力。


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


你进一步问,

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

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

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

于 2013-01-05T08:15:28.120 回答
2

该代码完全有效(在 MSVC 上)。你可以忽略警告作为红鲱鱼。

有两个问题需要考虑:

  1. 获取临时地址(又名:右值),根据标准 & 是不允许的
  2. 临时地址的生命周期被占用。

反问题 1:
MSVC 允许您通过扩展获取临时地址。因此,在您的情况下,临时地址将至少编译(由 MSVC 提供)。

反问题 2:
进一步保证临时String8("Exception")对象至少可以存活到表达式结束。请注意,表达式在 return from 之后结束WriteLine(),准确地说是;在 call 结束时的分号)。所以它是完全有效的。在这种情况下,您可以将警告视为红鲱鱼。

C++03 标准§12.2/3:

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

于 2013-01-05T08:04:07.747 回答