3

我得到了这个类:

class myClass
{
private:
      struct tm minDate, maxDate;
public:
      myClass();

      struct tm GetMinDate()  {return minDate;};
      struct tm GetMaxDate()  {return maxDate;};
};

和这个函数调用

SetMinMaxDate(struct tm *MinDate, struct tm *MaxDate);

以下代码

myClass myInstance;
SetMinMaxDate(&myInstance.GetMinDate(), &myInstance.GetMaxDate());

运行良好,使用 MSVC 2010 和 2005 不会生成警告。但是如果我用英特尔 C++ 编译它,我会收到警告

warning #1563: taking the address of a temporary

根据这个相关线程

临时对象(也称为右值)的生命周期与表达式相关联,并且在完整表达式的末尾调用临时对象的析构函数

SetMinMaxDate 复制使用指针传递的内容。指针本身不被存储。因此,在 SetMinMaxDate 返回之前,这 2 个临时 tm 元素应该是有效的。

这段代码有问题还是英特尔 C++ 的误报?

编辑: 我发现另一个非常有趣的帖子给出了这种行为的原因: 为什么临时获取右值的地址是非法的?

4

4 回答 4

7

这是一个有效的警告,因为SetMinMaxDate()不保证它不会存储该指针以供以后使用。而且由于您将指针传递给临时对象,因此如果SetMinMaxDate将其存储以供以后使用,那将是一个问题。

警告的另一个原因是,使用您的声明,可能SetMinMaxDate正在修改通过指针传入的 tm 结构,并且此类修改会丢失,因为它是指向临时对象的指针。

SetMinMaxDate最好声明为:

SetMinMaxDate(const struct tm & MinDate, const struct tm & MaxDate);

在这种情况下不会有警告。让const编译器知道它不会修改对象,并且&表明它不太可能尝试存储地址以供以后使用。

于 2013-05-23T13:41:51.443 回答
5

根据 C++11 标准的第 5.3.1/3 段:

一元运算符的结果&是指向其操作数的指针。操作数应该是一个左值或一个qualified-id。[...]

不仅警告是适当的,我还想知道为什么它不是错误。您的程序格式错误,因为临时变量不是左值。可能,MSVC 支持它作为编译器扩展 - 但这个扩展的价值是相当有争议的。

于 2013-05-23T13:43:09.603 回答
0

问:这段代码有问题还是英特尔 C++ 的误报?A:我在这段代码中看到了这个问题。

函数 GetMinDate() 返回一个理论上可以存储在处理器寄存器中的值。因此它没有地址。大多数编译器会将返回值存储在其生命周期转瞬即逝的临时变量中。到目前为止,没有问题。

 struct tm GetMinDate()  {return minDate;};

稍后您将引用此结果的“地址”

... &myInstance.GetMinDate() ...

现在你有问题了。临时地址可以很快被另一个操作使用,例如 myInstance.Get* Max *Date() 的结果。

@drahnr 推荐的实现是一个很好的解决方案。

由于 struct tm 很大,另一种但很差的方法是将参数作为值传递给 SetMinMaxDate()

SetMinMaxDate(struct tm MinDate, struct tm MaxDate);
于 2013-05-23T14:53:19.570 回答
0
myClass myInstance;
{
struct tm a,b;
a = myInstance.GetMinDate();
b = myInstance.GetMaxDate();
SetMinMaxDate(&a, &b);
}

应该如何实现它。

根据我灰色的记忆,你可能不会得到一个地址rvalue——这就是你所做的。

这么短:英特尔 C 是对的

于 2013-05-23T13:44:14.970 回答