The lifetime of an object is determined when the object is created and never changes after that. There is nothing you can do to an already-existing object that will cause its lifetime to change.
For your specific examples:
int&& foo() {
int n = 5;
return std::move(n);
}
foo
returns a dangling reference. The lifetime of n
ends when foo
returns. Since foo
returns a reference to n
, and n
's lifetime has ended, any read or write to the reference returned by foo
will result in undefined behavior.
int x = 0;
static_cast<int&&>(x);
static_cast<const int&>(x);
These casts do nothing. Even if the result was assigned to another variable, they would have no effect on the lifetime of x
.
std::move(0);
std::move(std::string("hello, world!"));
These both return dangling references. 0
and std::string("hello, world!")
both create temporary objects. Reference lifetime extension would extend their lifetimes to the lifetimes of std::move
's argument (since they are bound to that reference immediately at the moment they're created), but that argument's lifetime is shorter than that of the temporary objects anyway.
Some of your confusion seems to come from the so-called "reference lifetime extension" feature of C++. This does not, however, extend the lifetime of existing objects. It can only extend the lifetime of an object as it is being created.
If a temporary object is bound to a reference immediately upon creation then that temporary object's lifetime is extended to the lifetime of the reference.
That is, reference lifetime extension applies in all of the following cases:
// Here the string literal "Hello World" is converted to a to a temporary std::string
// which has its lifetime extended to the lifetime of foo
const std::string& foo = "Hello World";
// Here the return value of func is a temporary int object
// which has its lifetime extended to that of i
int func() { return 42; }
const int& i = func();
Reference lifetime extension does not apply in these situations:
// The temporary object created by the int literal 42 does not have
// its lifetime extended to that of i because it is not bound to i
// at the moment of its creation.
const int& func() { return 42; }
const int& i = func();
// The lifetime of the temporary std::string object created from the
// string literal "some string" does not get extended to the lifetime
// of f.member_ref because it is not bound to member_ref at the moment
// of its creation
struct Foo
{
const std::string& member_ref;
Foo(const std::string& s) : member_ref(s) {}
};
Foo f("some string");