Why Is Taking the Address of a Temporary Illegal

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



Leave a reply



Submit