Why Is It Illegal to Take the Address of an Rvalue Temporary

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.

What does it mean to take the address of an rvalue reference?

When you take an address of an rvalue reference, it returns a pointer to the object that reference is bound to, like with lvalue references. The object can be a temporary or not (if for example you cast an lvalue to rvalue reference like you do in your code).

int y = 5; foo(static_cast<int&&>(y)); does not create a temporary. This conversion is described in part 5.2.9/3 of the standard:

A glvalue, class prvalue, or array prvalue of type “cv1 T1” can be cast to type “rvalue reference to cv2 T2” if “cv2 T2” is reference-compatible with “cv1 T1”.

A temporary will be created if for example you call foo(1);.

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.

error: cannot take the address of an rvalue of type 'void'. Two classes with same workflow but one throws error

Change this line

m_sendEvent = Simulator::Schedule(Seconds(0.0), &ProactiveProducer::SendData(m_prefix), this);

to this

m_sendEvent = Simulator::Schedule(Seconds(0.0), &ProactiveProducer::SendData, this, m_prefix);

Reference: https://www.nsnam.org/doxygen/classns3_1_1_simulator.html#aec5dd434c42edd6c38ef249d2960c321

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.

Error taking address of temporary in Eclipse

If you really must do that, then do this instead:

MyNode copy = *itr;
MyNode *p1 = ©

As a comment said, attempting to take address of a temporary does not work because temporaries do not have valid memory address after the line they used in.

Getting the address of an rvalue

is: there is anyway to securely pass an rvalue reference (a.k.a. address of temporary) to another function without boringly storing it in a variable just to do that?

Yes, there is, like in the next example :

#include <iostream>

class MyClass {
public: MyClass(int a) : a(a) { }
int a;
};

void print(MyClass&& a) { std::cout << a.a << std::endl; }

int main() {
print( MyClass(1337) );
}

Is it legal to take the address of a const lvalue reference?

This is fine. In C++11 you can even do this:

int&& a = foo();
a = 123;

You can kind of think about temporaries like this (conceptually and in general):

x = func(); // translated as:

auto __temporary = func();
x = __temporary;
__destruct_value_now_and_not_later(__temporary);

Except if x is the definition of a reference type, the compiler notes that you're purposefully referring to the temporary value and extends its lifetime by removing the early destruction code, making it a normal variable.



Related Topics



Leave a reply



Submit