简体   繁体   中英

cout char* is different even when declared constant

I have a very simple code snippet:

#include <iostream>

using namespace std;

string getString() {
  return "test";
}

int main(){
  const char* testString = getString().c_str();
  cout << "string 1:" << testString << endl;
  string dummy[] = {"1","2","0"};
  cout << "string 2:" << testString << endl;
  return 0;
}

I expect the two couts will print the same output, but the output I got is

string 1:test
string 2:1

Can anyone explain why is this happening? Also, there are two things that I observed:

1) If dummy[] is of int type, then they will print the exact same strings test as expected.

2) If I first assign getString() to a string variable, then change the first line in main to const char* testString = variable.c_str(); then they will cout the same strings as expected.

The behavior is undefined.

const char* testString = getString().c_str();

getString returns a temporary object which is destroyed when the evaluation completes. As the result. testString points at internals of a destroyed object, causing undefined behavior.

In practice, it may happen that the data is still at that address for some time, that's why the first cout gives illusion of correctness.

You set pointer to a temporary object that will be deleted after this declaration

const char* testString = getString().c_str();

So the program has undefined behaviour.

The correct code could look like

const char * getString() {
  return "test";
}

int main(){
  const char* testString = getString();
//...

because string literals have static storage duration.

When you get a low level character pointer from a string object that manages the memory for that string, the pointer is only good for as long as that specific object is alive.

It's more narrow than that, actually. If you call any non-const members on the string object, it means you can't trust any values you got from previous calls to c_str() to still be good--even if the object destructor has not run.

#include <iostream>

using namespace std;

string getString() {
    return "test";
}

int main(){
    string testString = getString();
    const char * testCstring = testString.c_str();
    cout << "string 1:" << testCstring << endl;
    string dummy[] = {"1","2","0"};
    cout << "string 2:" << testCString << endl;
    return 0;
}

That's legal, but do not rely upon the pointer from c_str() after you have made any modifying change to the string you got it from -or- that string having been destroyed.

Also note there's no need to get a char * from a string in order to output it. Start thinking in terms of using string objects and don't go to char * unless you have a good reason.

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