取一个临时对象的地址
§5.3.1一元运算符,第3节
一元&运算符的结果是一个指向其操作数的指针。 操作数应该是一个左值或者是一个合格的id。
在这种情况下,“应该”是什么意思? 这是否意味着暂时的地址是错误的? 我只是想知道,因为g ++只给了我一个警告,而comeau拒绝编译下面的程序:
#include <string> int main() { &std::string("test"); }
g ++ 警告 : taking address of temporary
comeau 错误 : expression must be an lvalue or a function designator
有没有人有微软的编译器或其他编译器,可以testing这个程序,请? 提前致谢。
标准语言中的“应”一词意味着严格的要求。 所以,是的,你的代码是格式不正确(这是一个错误),因为它试图将地址运算符应用于非左值。
但是,这里的问题不是暂时性的 。 问题是,再次考虑一个非左值的地址。 临时对象可以是左值或非左值,具体取决于生成临时对象的expression式或提供对临时对象的访问。 在你的情况下,你有std::string("test")
– 一个function风格转换为非引用types,根据定义产生一个非左值。 因此,错误。
例如,如果您希望获得临时对象的地址,则可以通过这样做来解决这个限制
const std::string &r = std::string("test"); &r; // this expression produces address of a temporary
只要临时存在,结果指针保持有效。 还有其他方法可以合法获取临时对象的地址。 这只是你的具体方法是非法的。
当C ++标准中使用“shall”这个词时,意思是“必死”,如果一个实现不服从这个,就是错误的。
MSVC允许使用已弃用/ Ze(扩展启用)选项。 它在以前版本的MSVC中被允许。 它会生成一个启用了所有警告的诊断:
警告C4238:使用非标准扩展:用作左值的类右值。
除非使用/ Za选项(强制执行ANSI兼容性),否则:
错误C2102:'&'需要l值
C ++标准实际上是符合C ++实现的要求。 在写这些地方的目的是为了区分一致的实现必须接受的代码和一致性实现必须给出诊断的代码。
因此,在这种特殊情况下,如果右值的地址被采用,符合的编译器必须给出一个诊断。 这两个编译器都这样做,所以它们在这方面是一致的。
如果某个input引起诊断,则该标准不禁止生成可执行文件,即警告是有效的诊断。
&std::string("test");
是要求函数调用的返回值的地址(我们将忽略这个函数是一个ctor的事实无关)。 它没有一个地址,直到你把它分配给一些东西。 因此这是一个错误。
我不是标准专家,但对我来说这听起来像是一个错误。 g ++通常只会给出真正错误的警告。