Taking the address of a temporary object

§5.3.1 Unary operators, Section 3

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

What exactly does "shall be" mean in this context? Does it mean it's an error to take the address of a temporary? I was just wondering, because g++ only gives me a warning, whereas comeau refuses to compile the following program:

#include <string>

int main()
{
    &std::string("test");
}

g++ warning: taking address of temporary

comeau error: expression must be an lvalue or a function designator

Does anyone have a Microsoft compiler or other compilers and can test this program, please?


Solution 1:

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.

Solution 2:

When the word "shall" is used in the C++ Standard, it means "must on pain of death" - if an implementation does not obey this, it is faulty.

Solution 3:

It is permitted in MSVC with the deprecated /Ze (extensions enabled) option. It was allowed in previous versions of MSVC. It generates a diagnostic with all warnings enabled:

warning C4238: nonstandard extension used : class rvalue used as lvalue.

Unless the /Za option is used (enforce ANSI compatibility), then:

error C2102: '&' requires l-value

Solution 4:

&std::string("test"); is asking for the address of the return value of the function call (we'll ignore as irrelevant the fact that this function is a ctor). It didn't have an address until you assign it to something. Hence it's an error.

Solution 5:

The C++ standard is a actually a requirement on conformant C++ implementations. At places it is written to distinguish between code that conformant implementations must accept and code for which conformant implementations must give a diagnostic.

So, in this particular case, a conformant compiler must give a diagnostic if the address of an rvalue is taken. Both compilers do, so they are conformant in this respect.

The standard does not forbid the generation of an executable if a certain input causes a diagnostic, i.e. warnings are valid diagnostics.