4

I'm working on a form which has QT widget, I have to set some value in a QTextEdit field. I had to call a function which is declared like :

 void SDB::setDescription(const char *Description);

and when I call it by this method (i)

const char * desc = saveOptionsDesLineEditBox->text().toStdString().c_str();
SDB::setDescription(desc);

It shows unrecognised symbol in the widget's text box. but by calling by this second method (ii)

SDB::setDescription(saveOptionsDesLineEditBox->text().toStdString().c_str());

works fine. Why there is difference between these two methods?

Maverick33
  • 337
  • 3
  • 15
  • 1
    Related: http://stackoverflow.com/questions/5449368/is-this-a-proper-use-of-a-temporary-stdstring Dangling pointer –  May 30 '13 at 12:20
  • @0A0D I read this line on your mentioned link : The destructor for the temporary will not be called until after the function call returns. I guess this clears the doubt for me, thank you :) And so it means, in the called function I can use this value anywhere but once control returns, use of this would have undefined behavior? – Maverick33 May 30 '13 at 13:42

2 Answers2

7

The std::string returned by saveOptionsDesLineEditBox->text().toStdString() is a temporary. It goes out of scope at the end of the line, and is destroyed, along with its contents. Therefore, referring to the contained const char* returned by c_str() through desc in the next line is undefined behaviour.


When you call
SDB::setDescription(saveOptionsDesLineEditBox->text().toStdString().c_str());

all in the same statement, the temporary exists for long enough that setDescription can read and copy the c string safely.

I'd suggest something along the lines of

std::string desc = saveOptionsDesLineEditBox->text().toStdString();
SDB::setDescription(desc.c_str());

Strictly speaking this will incur one copy more than necessary (or a move if you have c++11), but who really cares here. Making the code simpler to understand is a good thing in its own right.

(Note, this is a guess, not having seen any of the function signatures, but it is pretty likely a good one.)

BoBTFish
  • 19,167
  • 3
  • 49
  • 76
  • 1
    Incidentally, in case anyone was thinking of it, I thought mentioning the "most important `const`" trick to avoid the extra copy was probably a bit much for the asker at this point. For those interested, see http://herbsutter.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/ If you don't fully understand the lifetime of temporaries, don't worry about how you can change it. – BoBTFish May 30 '13 at 12:31
3

I guess .toStdString() returns a std::string, not a . std::string& to some stable object.

If so, it is a temporary, that will be destroyed at the end of the full expression (that is the last ; in the line). Before that you asked a const char* from that temporary, and store it. When it is valid only as long as string lives.

You can fix the situation like this:

const auto& desc = saveOptionsDesLineEditBox->text().toStdString();
SDB::setDescription(desc.c_str());

or just put the whole expression in the setDescription call.

Balog Pal
  • 16,195
  • 2
  • 23
  • 37