The lifetime of the data pointed ccto coincides with the lifetime of the line from which it came (at best, if you change the line that is even shorter).
In your case, the return value foo()is temporary, which is destroyed at the end of initialization cc.
char *cc = foo().c_str(), char*, const char *cc, const char* - , c_str(). .
:
printf("%s", foo().c_str());
const string s = foo();
const char *cc = s.c_str();
string s = foo();
printf("%s", s.c_str());
std::cout << foo();