为什么有些编译器抱怨从构造函数中获取临时地址而有些则没有?
例如:
WriteLine(&String8("Exception"));
我假设抱怨的编译器没有将该地址存储在堆栈中,如果我忽略警告,它会爆炸。有没有办法让它在一条线上工作?最好/唯一的方法是返回地址的类上的静态方法吗?嗯,我不认为 String8 类上返回指针的静态方法会起作用,因为它将 String8 类保存到寄存器中,然后在 WriteLine() 中吃掉它
为什么有些编译器抱怨从构造函数中获取临时地址而有些则没有?
例如:
WriteLine(&String8("Exception"));
我假设抱怨的编译器没有将该地址存储在堆栈中,如果我忽略警告,它会爆炸。有没有办法让它在一条线上工作?最好/唯一的方法是返回地址的类上的静态方法吗?嗯,我不认为 String8 类上返回指针的静态方法会起作用,因为它将 String8 类保存到寄存器中,然后在 WriteLine() 中吃掉它
您提供的示例代码,
WriteLine(&String8("Exception"));
与标准 C++ 一样无效,除非该String8
类型定义了自定义地址运算符。
你问,
“为什么有些编译器抱怨从构造函数中获取临时地址,而有些则没有?”
一些编译器抱怨,因为 C++ 标准规定您不能使用内置地址运算符来获取临时地址:
C++11 §5.3.1/3:
“一元运算符的结果&
是指向其操作数的指针。操作数应该是一个左值或一个合格的 id。”
一些编译器,例如 Visual C++,不会抱怨,因为它们提供了将地址作为语言扩展的能力。
请注意,用户定义类型可以定义自定义地址运算符。因此,在您的情况下,它取决于String8
type。以及在编译器上。
你进一步问,
“有没有办法让它在一条线上工作?”
是的,您可以定义地址运算符。但这不是一个好主意。首先,它只会在标准库等方面产生问题,其次,这种需求非常罕见。
我只记得我认真考虑过这样一个解决方案的一个案例,即传递一个 COM 智能指针作为外参数。我没有定义地址运算符,而是定义了一个命名方法。它更清晰,不会干扰其他事情。
该代码完全有效(在 MSVC 上)。你可以忽略警告作为红鲱鱼。
有两个问题需要考虑:
反问题 1:
MSVC 允许您通过扩展获取临时地址。因此,在您的情况下,临时地址将至少编译(由 MSVC 提供)。
反问题 2:
进一步保证临时String8("Exception")
对象至少可以存活到表达式结束。请注意,表达式在 return from 之后结束WriteLine()
,准确地说是;
(在 call 结束时的分号)。所以它是完全有效的。在这种情况下,您可以将警告视为红鲱鱼。
C++03 标准§12.2/3:
临时对象被销毁作为评估完整表达式(1.9)的最后一步,该完整表达式(词法上)包含它们被创建的点。