PDA

View Full Version : QString use .c_str()?



therock1987
5th September 2010, 19:34
Qt 4.5 QString have a way to output a null terminaded string ( QString.cstr() )

wysota
5th September 2010, 20:51
QString::toLatin1(), QString::toLocal8Bit(), QString::toAscii() and then QByteArray::constData().

jonthom
19th October 2010, 16:31
Could also do this:


#include <string>

char * c_string = QString().toStdString().c_str();

jonthom
20th October 2010, 18:35
Could also do this:


#include <string>

char * c_string = QString().toStdString().c_str();

edit*


const char * c_string = QString().toStdString().c_str();

wysota
20th October 2010, 18:43
This code is incorrect. It will segfault in many situations.

jonthom
20th October 2010, 18:50
how so? I use this method often to convert QStrings into c-strings and its never seg faulted. In what situtation does it seg fault?

jonthom
20th October 2010, 18:59
maybe the confusion here is my semi pseudo code:


QString str = "Some string";
const char * c_string = str.toStdString().c_str();

not


const char * c_string = QString().toStdString().c_str();

I agree putting the latter line into code would probably segfault or return NULL to the pointer. Sorry for the confusion.

wysota
20th October 2010, 19:04
No, that's still wrong. The whole concept of doing what you are doing is wrong.

Timoteo
20th October 2010, 19:08
Is this the whole "intermediate references smell like poo" thing?:cool:

jonthom
20th October 2010, 19:09
Well could you explain why you think that? I dont see how its any different from converting to a QBtyeArray and pulling the char * out of it.

wysota
20th October 2010, 19:20
Well could you explain why you think that? I dont see how its any different from converting to a QBtyeArray and pulling the char * out of it.

Well, this is wrong too of course:

QString str = "xxx";
const char *cstr = str.toAscii().constData();

This is much better although might still be wrong in some cases:

QString str = "xxx";
QByteArray ba = str.toAscii();
const char *cstr = ba.constData();

This is ok:

QString str = "xxx";
QByteArray ba = str.toAscii();
const char *cstr = strcpy(ba.constData());
So is this:

QString str = "xxx";
QByteArray ba = str.toAscii();
someCallThatNeedsACStr(ba.constData());

jonthom
20th October 2010, 19:31
Ok i see what you mean now. Yes, if you want a deep copy that you can manipulate safely strcpy() is the way to go. Other than that, this method is effectively the same as using a std::string as the medium. My code was intended for use as an argument to a function that wants a c-str. Also, getting the shallow copy isnt necessarily "wrong" it just depends on what you intend to do with it.

wysota
20th October 2010, 19:58
Other than that, this method is effectively the same as using a std::string as the medium.
The problem is that your code uses a temporary object which immediately gets destroyed so the result of c_str() is immediately invalid - it points to a region of memory which might or might not contain the string.

jonthom
20th October 2010, 20:27
Yes you're right. QString().toStdString() creates a temporary std::string variable with the string value of the QString. The c_str() routine returns a pointer to memory held by that temp std::string not the original QString. I never thought of that but I really only use this method to immediately use the data for a function call. The function you use it on must deep copy the data before any other operation overwrites it. It is a very dangerous statement and can result in a segfault. Perhaps I should rethink using it. Thanks for expounding your opinion.

ok hows this:


#include <string>

QString str = "xxx";
std::string stdstr = str.toStdString();
const char * cstr = stdstr.c_str();

wysota
20th October 2010, 20:55
I never thought of that but I really only use this method to immediately use the data for a function call.
If you go through a temporary, the data might already be invalid when you enter the function.


The function you use it on must deep copy the data before any other operation overwrites it.
It's already too late. Initialization of the function itself or any of its local variables might overwrite the temporary. Of course unless the temporary is created during the function call:

func(str.toStdString().c_str());


ok hows this:


#include <string>

QString str = "xxx";
std::string stdstr = str.toStdString();
const char * cstr = stdstr.c_str();
This is ok as long as stdstr lives.

jonthom
21st October 2010, 02:14
Ok so I just went back to bjarne. According to him, a temp variable is destroyed at the end of the expression in which it is used. Becuase a function call in an expression is executed as part of the expression, the temp variable memory block will exist and be valid in this context:


QString str = "xxx";
(void)somefunction(str.toStdString().c_str());

so that is correct code.

jonthom
21st October 2010, 02:18
It's already too late. Initialization of the function itself or any of its local variables might overwrite the temporary.

Thats not true if the function call and the temp are in a single statement (see above).



Of course unless the temporary is created during the function call:

func(str.toStdString().c_str());


That was my point in the first place. I would only use a statement like this during the function call.

const char * str = QString().toStdString().c_str();

by itself definately goes out of scope. I was only using that as an example of the syntax

wysota
21st October 2010, 02:21
const char * str = QString().toStdString().c_str();

by itself definately goes out of scope. I was only using that as an example of the syntax

Try to avoid that. People tend to copy and paste code directly from this forum to their applications without changing it or reading the whole thread that discusses a particular piece of code. And then they will write somewhere that at Qt Centre they gave them code that didn't work.

jonthom
21st October 2010, 02:24
Try to avoid that. People tend to copy and paste code directly from this forum to their applications without changing it or reading the whole thread that discusses a particular piece of code. And then they will write somewhere that at Qt Centre they gave them code that didn't work.

So noted. Thanks for the interesting debate.