Is it safe to use c_str() on a temporary string?

The code exhibits undefined behavior.

get_data() returns a temporary which expires at the end of the full expression (*):

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

data points to an internal of that object, so after the temporary ends you are left with a dangling pointer. Accessing it leads to Undefined Behavior. So the next line std::cout << data << "\n"; makes the whole program exhibit Undefined Behavior.

*) There is an exception to this rule which doesn't apply here. If a prvalue is directly bound to a reference, the lifetime of the prvalue is extended to the lifetime of the reference.

For instance, this would have been fine:

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