I have a char* p
, which points to a \\0
-terminated string. How do I create a C++ string
from it in an exception-safe way?
Here is an unsafe version:
string foo()
{
char *p = get_string();
string str( p );
free( p );
return str;
}
An obvious solution would be to try-catch - any easier ways?
You can use shared_ptr
from C++11 or Boost :
string
foo()
{
shared_ptr<char> p(get_string(), &free);
string str(p.get());
return str;
}
This uses a very specific feature of shared_ptr
not available in auto_ptr
or anything else, namely the ability to specify a custom deleter; in this case, I'm using free
as the deleter.
Can I ask you what exception you are expecting in your example?
On many platforms (Linux, AIX) new or malloc will never fail and your app will get killed by the os if you run out of memory.
See this link: What happens when Linux runs out of memory.
Yup - stack-based unwinding. Modern C++ Design has the general solution but in this case you can use
struct Cleanup {
void* toFree;
Cleanup(void* toFree) : toFree(toFree) {}
~Cleanup() { free(toFree); }
private:
Cleanup(Cleanup&);
void operator=(Cleanup&);
};
No matter what happens with your std::string, free(toFree) will be called when your Cleanup object goes out of scope.
Well, p
does not point to a 0-terminated string if get_string()
returns NULL; that's the problem here, since the std::string
constructors that take a pointer to 0-terminated C string cannot deal with NULL, which is as much a 0-terminated C string as two dozens of bananas are.
So, if get_string()
is your own function, as opposed to a library function, then maybe you should make sure that it cannot return NULL. You could for instance let it return the sought std::string
itself, since it knows it's own state. Otherwise, I'd do this, using the Cleanup
from this answer as a helper to guarantee that p
cannot leak (as suggested by Martin York in a comment):
string foo()
{
const char* p = get_string();
const Cleanup cleanup(p);
const std::string str(p != NULL ? p : "");
return str;
}
We commonly use ScopeGuard for these cases:
string foo()
{
char *p = get_string();
ScopeGuard sg = MakeGuard(&free, p);
string str( p );
return str;
}
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.