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
How to Avoid the Diamond of Death When Using Multiple Inheritance
Find Out Whether a C++ Object Is Callable
C++ Array Assignment of Multiple Values
Shared-Memory Ipc Synchronization (Lock-Free)
How to Sort an Stl Map by Value
C and C++ Programming on Ubuntu 11.10
How to Get Memory Usage Under Windows in C++
What Is the Easiest Way to Print a Variadic Parameter Pack Using Std::Ostream
Why Is It Allowed to Pass R-Values by Const Reference But Not by Normal Reference
How to Make C++ Cout Not Use Scientific Notation
Gcc C++ "Hello World" Program -> .Exe Is 500Kb Big When Compiled on Windows. How to Reduce Its Size
C++: Argument Passing "Passed by Reference"
Variable Assignment in an "If" Condition
Scope of Variables in If Statements
C++ Compare Char Array with String
How to Set a Breakpoint in Gdb Where the Function Returns