我上了这堂课:
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没有生成任何警告。但是,如果我用intel C ++编译它,我会得到警告
warning #1563: taking the address of a temporary
临时对象(也称为右值)的生命周期是绑定的 表达式和临时对象的析构函数是 在完整表达结束时调用
SetMinMaxDate复制用指针传递的内容。指针本身不存储。 因此,在SetMinMaxDate返回之前,2个临时tm元素应该有效。
此代码中是否存在问题,或者这是英特尔C ++的误报?
修改 我找到了另一篇非常有趣的帖子,说明了这种行为的原因: Why is it illegal to take the address of an rvalue temporary?
答案 0 :(得分:6)
这是一个有效的警告,因为SetMinMaxDate()
不保证它不会存储该指针供以后使用。并且由于您正在向临时传递指针,如果SetMinMaxDate
存储它以供以后使用,那将是一个问题。
警告的另一个原因是,使用声明,可能SetMinMaxDate
修改通过指针传入的tm结构,这样的修改会丢失,因为它是指向临时对象。
SetMinMaxDate
最好声明为:
SetMinMaxDate(const struct tm & MinDate, const struct tm & MaxDate);
在这种情况下,没有警告。 const
允许编译器知道它不会修改对象,而&
表示它不太可能试图存储该地址以供日后使用。
答案 1 :(得分:5)
根据C ++ 11标准的第5.3.1 / 3段:
一元
&
运算符的结果是指向其操作数的指针。 操作数应为左值或限定ID 。 [...]
不仅警告是合适的,我更想知道为什么它不是错误。你的节目是不正确的,因为临时不是左撇子。可能,MSVC支持这作为编译器扩展 - 但这个扩展的价值是相当有争议的。
答案 2 :(得分:0)
myClass myInstance;
{
struct tm a,b;
a = myInstance.GetMinDate();
b = myInstance.GetMaxDate();
SetMinMaxDate(&a, &b);
}
应如何实施它。
根据我的灰色记忆,你可能无法获得rvalue
的地址 - 这就是你所做的。
如此简短:英特尔C是对的
答案 3 :(得分:0)
函数GetMinDate()返回一个理论上可以存储在处理器寄存器中的值。因此它没有地址。大多数编译器会将返回值存储在一个临时的生命周期中。到目前为止,没问题。
struct tm GetMinDate() {return minDate;};
稍后您在
中引用此结果的“地址”... &myInstance.GetMinDate() ...
现在你有问题了。另一个操作可以快速使用临时地址,例如myInstance.Get * Max * Date()的结果。
@drahnr建议实施是一个很好的解决方案。
另一个但是结构tm较差的方法是将参数传递给SetMinMaxDate()作为值
SetMinMaxDate(struct tm MinDate, struct tm MaxDate);