Say I have something like this
extern "C" void make_foo (char** tgt) {
*tgt = (char*) malloc(4*sizeof(char));
strncpy(*tgt, "foo", 4);
}
int main() {
char* foo;
make_foo(&foo);
std::string foos{{foo}};
free(foo);
...
return 0;
}
Now, I would like to avoid using and then deleting the foo
buffer. I.e., I'd like to change the initialisation of foos
to something like
std::string foos{{std::move(foo)}};
and use no explicit free
.
Turns out this actually compiles and seems to work, but I have a rather suspicious feel about it: does it actually move the C-defined string and properly free the storage? Or does it just ignore the std::move
and leak the storage once the foo
pointer goes out of scope?
It's not that I worry too much about the extra copy, but I do wonder if it's possible to write this in modern move-semantics style.
char* is a pointer to a character. char is a character. A string is not a character. A string is a sequence of characters.
Use std::string when you need to store a value. Use const char * when you want maximum flexibility, as almost everything can be easily converted to or from one.
You can't really "assign a string" to a char * , because although a char* parameter is sometimes referred to as a "string parameter", it isn't actually a string, it's a pointer (to a string).
std::string constructor #5:
Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if s does not point at an array of at least Traits::length(s)+1 elements of CharT, including the case when s is a null pointer.
Your C-string is copied (the std::move
doesn't matter here) and thus it is up to you to call free
on foo
.
A std::string
will never take ownership.
Pointers don't have any special move semantics. x = std::move(my_char_ptr)
is the same as x = my_char_ptr
. They are not similar in that regard to, say, std::vector
's, in which moving takes away the allocated space.
However, in your case, if you want to keep existing heap buffers and treat them as strings - it can't be using std::string
's, as they can't be constructed as a wrapper of an existing buffer (and there's small-string optimization etc.). Instead, consider either implementing a custom container, e.g. with some string data buffer (std::vector<char>
) and an std::vector<std::string_view>
, whose elements point into that buffer.
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