3

I got this class:

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

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

and this function call

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

the follwing code

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

Works well and with MSVC 2010 and 2005 no warnings are generated. But if i compile it with intel C++ i get the warning

warning #1563: taking the address of a temporary

According to this related thread

The lifetime of the temporary object (also known as an rvalue) is tied to the expression and the destructor for the temporary object is called at the end of the full expression

SetMinMaxDate copies the content passed with pointers. The pointer itself is not stored. So the 2 temporary tm elements should be valid until SetMinMaxDate has returned.

Is there a problem in this code or is this a false positive of intel C++?

EDIT: I found another very interesting post that gives a reason for this behavior: Why is it illegal to take the address of an rvalue temporary?

Community
  • 1
  • 1
RED SOFT ADAIR
  • 12,032
  • 10
  • 54
  • 92

4 Answers4

7

It is a valid warning because SetMinMaxDate() makes no guarantees that it will not store that pointer for later use. And since you are passing a pointer to a temporary, if SetMinMaxDate stored it for later use, it would be a problem.

Another reason for the warning is that with the declaration you have, maybe SetMinMaxDate is modifying the tm structs passed in via pointer and such modifications would get lost since it is a pointer to a temp object.

SetMinMaxDate would be better declared as:

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

there would be no warning in this case. The const lets the compiler know it will not be modifying the object and the & indicates that it is unlikely to be trying to store the address for later.

Brandon
  • 38,310
  • 8
  • 82
  • 87
  • I get your point about telling the compiler "may modify", "may store etc.". But what does actually happen? The member functions return tm structure objects on the stack and the address of these objects is passed. Although this may not be conform to the c++ standard and the called function may do invalid things i don't see any technical caveats. The code is a mixture of non const legacy C code and old C++ code. Of course there are many ways of improvement. But thats not my question here. Thanks for your answer! – RED SOFT ADAIR May 23 '13 at 14:05
5

Per paragraph 5.3.1/3 of the C++11 Standard:

The result of the unary & operator is a pointer to its operand. The operand shall be an lvalue or a qualified-id. [...]

Not only the warning is appropriate, I am rather wondering why it is not an error. Your program is ill-formed, since temporaries are not lvalues. Probably, MSVC supports this as a compiler extension - but the value of this extension is rather arguable.

Andy Prowl
  • 124,023
  • 23
  • 387
  • 451
0
myClass myInstance;
{
struct tm a,b;
a = myInstance.GetMinDate();
b = myInstance.GetMaxDate();
SetMinMaxDate(&a, &b);
}

how you should implement it.

According to my gray rememberings you may not get the address of an rvalue - that is what you do.

So short: Intel C is right

drahnr
  • 6,782
  • 5
  • 48
  • 75
0

Q: Is there a problem in this code or is this a false positive of intel C++? A: I see this a problem in this code.

The function GetMinDate() returns a value which, theoretically, could be stored in a processor register(s). Thus it has no address. Most compilers will store the return value in a temporary whose lifetime is fleeting. So far, no problem.

 struct tm GetMinDate()  {return minDate;};

Later you reference the "address" of this result in

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

Now you have a problem. The address of the temporary could quickly be used by another operation like the result of myInstance.Get*Max*Date().

@drahnr recommended implementation is a good solution.

Another, but poor approach as struct tm is large, would be to pass the parameters to SetMinMaxDate() as values

SetMinMaxDate(struct tm MinDate, struct tm MaxDate);
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • "The address of the temporary could quickly be used by another operation like the result of myInstance.Get*Max*Date()." Not true. See http://stackoverflow.com/questions/584824/guaranteed-lifetime-of-temporary-in-c – RED SOFT ADAIR May 23 '13 at 14:59