在临时字符串上使用c_str()是否安全?

时间:2019-03-28 23:35:00

标签: c++ string object-lifetime

movieReq.onreadystatechange = function () {
    if (this.readyState == 4 && this.status == 200) {
        var parsedObj = JSON.parse(movieReq.responseText);
        mO.imdbId = parsedObj['imdb_id'];
    }
};

“ Hello”正在我的机器上打印;但是,我被认为这种行为是未指定的,即特定于实现的。我是正确的还是判断返回的字符串是不可变的并且始终限定为常量,它会始终显示“ Hello”?

2 个答案:

答案 0 :(得分:25)

该代码表现出未定义的行为。

get_data()返回一个临时值,该值在完整表达式(*)的末尾到期:

const char* data = get_data().c_str() ;
//                 ^~~~~~~~~~         ^
//                 this evaluates     |
//                 to a prvalue       |
//                                    temporary expires here

data指向该对象的内部,因此在临时结束之后,您将剩下一个悬空的指针。访问它会导致未定义的行为。因此,下一行std::cout << data << "\n";使整个程序表现出未定义的行为。


*)此规则有一个例外,此处不适用。如果将prvalue直接绑定到引用,则将prvalue的生存期延长到引用的生存期。

例如,这很好:

int main()
{
    const std::string& ref = get_data();
    const char* data = ref.c_str();
    std::cout << data << "\n";
    return 0;
}

答案 1 :(得分:10)

是的,但不是您的操作方式。

如果您这样做:

std::cout << get_data().c_str() << '\n';

你会没事的。

那是因为可以保证临时文件在其创建的完整表达式的生命期内都可以存在。在某些非常特殊的情况下,它可以生存更长的时间。

如果将const引用绑定到临时目录,则其生存期将延长为其所绑定名称的生存期。因此,这样的代码:

std::string const &x = get_data();
std::cout << x.c_str() << '\n';

也将起作用,因为get_data返回的临时目录将绑定到名为x的引用,并且只要x仍然是要使用的有效名称,该临时目录仍会存在。