Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

The lifetime of a temporary to which several references are bound in C++

The C++ standard draft N4296 says

[class.temporary/5] The second context is when a reference is bound to a temporary. The temporary to which the reference is bound or the temporary that is the complete object of a subobject to which the reference is bound persists for the lifetime of the reference except...

So I want to know what happens if two or more references are bound to a temporary. Is it specific in the standard? The following code may be an example:

#include <iostream> //std::cout
#include <string>   //std::string
const std::string &f() {
    const std::string &s = "hello";
    static const std::string &ss = s;
    return ss;
}
int main() {
    const std::string &rcs = f();
    std::cout << rcs; //empty output
                      //the lifetime of the temporary is the same as that of s
    return 0;
}

If we change the bounding order, the case is different.

#include <iostream> //std::cout
#include <string>   //std::string
const std::string &f() {
    static const std::string &ss = "hello";
    const std::string &s = ss;
    return ss;
}
int main() {
    const std::string &rcs = f();
    std::cout << rcs; //output "hello"
                      //the lifetime of the temporary is the same as that of ss
    return 0;
}

The compilation is done on Ideone.com.

I guess [class.temporary/5] only holds when the first reference is bound to the temporary, but I cannot find an evidence in the standard.

like image 610
xskxzr Avatar asked Nov 21 '15 17:11

xskxzr


People also ask

When does the lifetime of a reference begin and end?

The lifetime of a reference begins when its initialization is complete and ends as if it were a scalar object. Note: the lifetime of the referred object may end before the end of the lifetime of the reference, which makes dangling references possible.

What is the lifetime of an object or reference?

Every object and reference has a lifetime, which is a runtime property: for any object or reference, there is a point of execution of a program when its lifetime begins, and there is a moment when it ends.

What is the lifetime of a temporary object created by default?

The lifetime of a temporary object created when evaluating the default arguments of a default or copy constructor used to initialize an element of an array ends before the next element of the array begins initialization.

When does the lifetime of an object end in C++?

The lifetime of an object ends when: if it is of a non-class type, the object is destroyed (maybe via a pseudo-destructor call) (since C++20), or if it is of a class type, the destructor call starts, or the storage which the object occupies is released, or is reused by an object that is not nested within it.


1 Answers

This is a defect in that section that I reported as http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_active.html#1299 .

The proposed resolution is to add a term "temporary expressions". Life-time extension only happens for objects referred to by temporary expressions.

Here's my original report which I privately emailed. I think it makes clear what it's about

In the model of the Standard, there appears to be a distinction about temporary objects, and temporary expressions.

Temporary objects are created by certain operations operations, like functional casts to class types. Temporary objects have a limited specified lifetime.

Temporary expressions are expressions that are so attributed because they are used to track whether or not an expression refers to a temporary object for the purpose of determining whether or not the lifetime of their referent is lengthened when bound by a reference. Temporary expressions are compile time entities.

Several paragraphs refer to "temporaries", but do not explicitly specify whether they refer to temporary objects referred to by arbitrary expressions, or whether they refer only to temporary expressions. The paragraphs about RVO (paragraph 12.8p31) use "temporary" in the sense of temporary objects (they say such things like "temporary class object that has not been bound to a reference"). The paragraphs about lifetime lengthening (sub-clause 12.2) refer to both kinds of temporaries. For example, in the following, "*this" is not regarded as a temporary, even though it refers to a temporary

struct A { A() { } A &f() { return *this; } void g() { } };

// call of g() is valid: lifetime did not end prematurely
// at the return statement
int main () { A().f().g(); }

As another example, core issue 462 handles about temporary expressions (making a comma operator expression a temporary, if the left operand was one). This appears to be very similar to the notion of "lvalue bitfields". Lvalues that track along that they refer to bitfields at translation time, so that reads from them can act accordingly and that certain reference binding scenarios can emit diagnostics.

like image 132
Johannes Schaub - litb Avatar answered Nov 15 '22 05:11

Johannes Schaub - litb