Taking the Address of a Temporary Object

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.

c++ taking the address of a temporary object

The first snippet does rightfully not compile because, as the compiler said, you cannot take the address of a temporary object because it would be destroyed at the end of the expression (here: the assignment). Thus, saving its address would be meaningless.

The second snippet does compile, but is still incorrect although it might seem to work for the reasons stated here (at least if you try to access the object through the pointer).

Simplest fix for error: taking the address of a temporary object?

Is there a compiler switch to make it tolerate such constructs?`

-Wno-address-of-temporary...

But that would be just wrong. Compiling such code in C++ will result in a dangling pointer pointing to a memory of an object whose lifetime ended. The lifetime of temporary ends on ; in that code - after the assignment, the pointer is just invalid.

What's the smallest code change to make such code compile using clang++? Maybe the following?

The code b) is error prone - it leaves a pointer pointing to an object whose lifetime has ended.

I guess the "smallest" could be:

// in C++
context a,*ctx=&a;
// in C
struct context a={0},*ctx=&a;

Och, the smallest change would be to move the compund literal to previous line.

struct context t = {0};
struct context* ctx = &t;

Taking the address of a returned temporary object

makeFoo and copy elision (which as you noted is guaranteed in this specific example since C++17) don't even matter.

activeFoo can never be dangling. If it was pointing to an object after its lifetime ended, then the destructor of that object would have reset activeFoo to nullptr, meaning it cannot be pointing to the object, a contradiction. That is assuming the destructor is called for every created object of type Foo. Technically this might not always be the case if you placement-new objects explicitly, although it should.

I would however not generally expect a static analyzer to figure out this logic. Without some details on the static analyzer or what exactly it complains about, it will be hard to say more.

Taking the address of a temporary object of type 'z3::expr'

z3::expr_vector is a typedef for z3::ast_vector_tpl, whose operator[] returns elements by value, ie a temporary copy. So your z3::expr_vector example fails, because it is illegal to take the memory address of a temporary.

AFAICS, ast_vector_tpl does not have any methods that return access to its elements by reference/pointer, only by value. Neither does its iterator (so, something like z3::expr* t1 = &*(x.begin()); would not work, either).

std::vector, on the other hand, has an operator[] (and an iterator with an operator*) that returns access to its elements by reference instead, which is why your std::vector example works.

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