c++临时函数和构造函数

C++ temporaries and constructors

本文关键字:构造函数 函数 c++      更新时间:2023-10-16

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

例如:

WriteLine(&String8("Exception"));

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

中吃掉它

您给出的示例代码,

WriteLine(&String8("Exception"));

无效的作为标准c++,除非String8类型定义了自定义的地址操作符。


你问

,

为什么有些编译器会抱怨从构造函数中获取临时对象的地址,而有些则不会?

有些编译器会抱怨,因为c++标准规定不能使用内置地址操作符来获取临时对象的地址:

c++ 11§5.3.1/3 :
一元&操作符的结果是指向其操作数的指针。操作数应为左值或限定id。”

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


注意,用户自定义类型可以定义自定义地址操作符。因此,在您的情况下,它取决于String8类型


你进一步问,

“有没有办法让它在一行中工作?

是的,可以定义地址操作符。但这不是个好主意。首先,它只会给标准库等带来问题,其次,这样做的需求非常少。

我只记得一个我认真考虑过这种解决方案的情况,即传递一个COM智能指针作为输出参数。我没有定义地址操作符,而是定义了命名方法。它更清晰,而且不会干扰其他东西。

代码完全有效(在MSVC上)。你可以忽略这个警告,把它当作转移注意力的话题。

有两个问题需要考虑:

  1. 获取临时(a.k.)的地址。a: rvalue),根据标准&
  2. 是不允许的。
  3. 占用临时用户地址的生存时间。

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

Counter Issue 2:
此外,还保证临时String8("Exception")至少在表达式结束之前有效。注意,表达式结束于WriteLine()的返回值之后,确切地说是; ( call结尾的分号)。所以它是完全有效的。在这种情况下,您可以将警告视为转移注意力。

c++ 03 Standard§12.2/3:

临时对象在(词法上)包含创建它们的点的完整表达式(1.9)求值的最后一步被销毁。