Why is it illegal to take the address of an rvalue temporary?
You're right in saying that "temporaries are not guaranteed to even have storage", in the sense that the temporary may not be stored in addressable memory. In fact, very often functions compiled for RISC architectures (e.g. ARM) will return values in general use registers and would expect inputs in those registers as well.
MSVS, producing code for x86 architectures, may always produce functions that return their values on the stack. Therefore they're stored in addressable memory and have a valid address.
Taking the address of a temporary object
The word "shall" in the standard language means a strict requirement. So, yes, your code is ill-formed (it is an error) because it attempts to apply address-of operator to a non-lvalue.
However, the problem here is not an attempt of taking address of a temporary. The problem is, again, taking address of a non-lvalue. Temporary object can be lvalue or non-lvalue depending on the expression that produces that temporary or provides access to that temporary. In your case you have std::string("test")
- a functional style cast to a non-reference type, which by definition produces a non-lvalue. Hence the error.
If you wished to take address of a temporary object, you could have worked around the restriction by doing this, for example
const std::string &r = std::string("test");
&r; // this expression produces address of a temporary
whith the resultant pointer remaining valid as long as the temporary exists. There are other ways to legally obtain address of a temporary object. It is just that your specific method happens to be illegal.
Taking address of temporary - workaround needed
Integer i(12);
foo(&i);
That gets rid of the "taking the address of a temporary" problem, which is what you have. You're not passing the address of a local variable (which the above does, and is indeed ok in this case), you're grabbing the address of a temporary.
Obviously, if foo
tries to hold on to that pointer one way or another, you'll have issues down the line.
intel++: warning #1563: taking the address of a temporary - false positive?
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.
warning: taking address of temporary - C++
The offending line is the third of.
Number object;
Command *commands[3];
commands[0] = &SimpleCommand(&object, &Number::dubble); // "warning: taking address of temporary"
In this, SimpleCommand(&object, &Number::dubble)
constructs a temporary, which will cease to exist at the end of the statement, and the &
takes its address. Hence the warning - the pointer will be dangling (pointing to an object that no longer exists). Any dereferencing of that pointer will cause undefined behaviour. A compiler is not required to diagnose this, but yours is doing you a favour.
Simply do as you have with other objects: construct the object and then store its address.
SimpleCommand simple(&object, &Number::dubble);
commands[0] = &simple;
Note that this will encounter the same problem if command[0]
is used after simple
ceases to exist. More realistic code (e.g. not everything within a toy main()
, as noted by "Useless in comments) can easily have the problem of commands[0]
continuing to exist - and being used - after the object it points to ceases to exist. That also causes undefined behaviour - but it is less likely that the compiler will be able to recognise that and issue a warning.
Related Topics
Specialization of Member Function Template After Instantiation Error, and Order of Member Functions
Any Good Reason Why Assignment Operator Isn't a Sequence Point
C++ Dynamic Array Initialization with Declaration
Seeking Code Stub Generator (From Header Files)
Advantage of Using Trailing Return Type in C++11 Functions
What Does the & (Ampersand) at the End of Member Function Signature Mean
How to Check If a File Is Gzip Compressed
How to Use the Ansi Escape Code for Outputting Colored Text on Console
What Is the Size of Float and Double in C and C++
How to Store Variant Data in C++
How to Dynamically Allocate Arrays in C++
What Is the Cin Analougus of Scanf Formatted Input
What Is the Array Form of 'Delete'