简体   繁体   中英

C++ temporary variable lifetime?

I know this is valid in C++, because temporary from std::string("xxx") lives to the end of the full expression it appears in.

printf("%s\n", std::string("xxx").c_str());

And this is valid too:

std::string f1() {
    return std::string("xxx");
}

void g1() {
    printf("%s\n", f1().c_str());
}

But is this valid? if not, why?

const char* f2() {
    return std::string("xxx").c_str();
}

void g2() {
    printf("%s\n", f2());
    // or: std::string x = f2(); // is this valid?
}

The temporary std::string inside of f2 is destroyed when the function returns. The char* will be dangling.

EDIT: In response to the comment, std::string x = f2() is also not valid. It's still bad to initialize a std::string from a dangling pointer.

The exact same rule applies. The full-expression in which the std::string was created in f2 is

std::string("xxx").c_str()

together with the construction of the return value from it.

After this expression executed and the construction of the return value executed, the temporary std::string("xxx") will be destroyed. Since destruction of the temporary std::string makes the const char* obtained from .c_str() and copied into the return value invalid, the return value of the function cannot be used in any way.

For f1 the same applies (details relating to temporary materialization and copy elision, especially in C++17, aside). The temporary std::string is destroyed after construction of the return value. But in this case this is not a problem, because the return value is not a pointer to something that was destroyed, but an independent std::string object itself. This std::string object will live until the end of the full-expression in which the call to f1 appears, ie until the end of

printf("%s\n", f1().c_str())

The following would be fine as well:

std::string f3() {
    return std::string("xxx").c_str();
}

Here again, a new std::string is created in the return value, which will live until the end of the full-expression in which f3 is called.


In practice, for f1 , since std::string("xxx"); is already a prvalue of type std::string , copy elision will be applied, so that there is really only one temporary object, the return value of f1 . The intermediate temporary will be eliminated and the return value directly constructed from "xxx" . This is mandatory since C++17 and was allowed and common before C++17.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM