I'm still learning c++, so please bear with me. I'm writing a simple wrapper around boost filesystem paths -- I'm having strange issues with returning temporary strings. Here's my simple class (this is not exact, but pretty close):
typedef const char* CString;
typedef std::string String;
typedef boost::filesystem::path Path;
class FileReference {
public:
FileReference(const char* path) : mPath(path) {};
// returns a path
String path() const {
return mPath.string();
};
// returns a path a c string
CString c_str() const {
return mPath.string().c_str();
};
private:
Path mPath;
}
With the little test code below:
FileReference file("c:\\test.txt");
OutputDebugString(file.path().c_str()); // returns correctly c:\test.txt
OutputDebugString(file.c_str()); // returns junk (ie îþîþîþîþîþîþîþîþîþîþî.....)
I'm pretty sure this has to deal with temporaries, but I can't figure out why that would be -- shouldn't everything be copying correctly?
CString c_str() const {
return mPath.string().c_str();
};
mPath.string()
returns a copy of a std::string
. That copy is stored in a temporary which will be destroyed at the end of this expression.
.c_str()
returns a pointer to memory which will be destroyed when the string is destroyed, i.e. at the end of this expression.
You are returning a pointer to memory which is already destroyed.
Looks like mPath.string()
returns a string by value. That temporary string object is destructed as soon as FileReference::c_str() returns, so its c_str() becomes invalid. With such a model, it's not possible to create a c_str()
function without introducing some kind of class- or static-level variable for the string.
Consider the following alternatives:
//Returns a string by value (not a pointer!)
//Don't call it c_str() - that'd be misleading
String str() const
{
return mPath.string();
}
or
void str(String &s) const
{
s = mPath.string();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With