Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to use std::basic_string as a wrapper around char*?

I have third party library that returns char* (and wchar_t*) that are created in it by strdup (and wcsdup functions respectively).

I want to avoid calling free manually at the end of my code.

Is it possible to write an allocator for std::basic_string so that it would handle dealing with this c-strings returned by this library? Ideally I don't want to allocate any new memory at all and use memory blocks that were returned (strings are supposed to be constant).

like image 810
Dmitrii Motorygin Avatar asked May 22 '19 13:05

Dmitrii Motorygin


People also ask

Is std::string a char *?

We know that both string::c_str or string::data functions returns const char*. To get a non-const version, we can use the const_cast operator, which removes the const attribute from a class. This works in constant time as no copying is involved.

Should I use std::string or * char?

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.

How do I convert a string to a char in C++?

The c_str() and strcpy() function in C++ C++ c_str() function along with C++ String strcpy() function can be used to convert a string to char array easily. The c_str() method represents the sequence of characters in an array of string followed by a null character ('\0'). It returns a null pointer to the string.

Should I use std::string?

h functions when you are declaring string with std::string keyword because std::string strings are of basic_string class type and cstring strings are of const char* type. Pros: When dealing exclusively in C++ std:string is the best way to go because of better searching, replacement, and manipulation functions.


2 Answers

Sadly, std::string does its own memory management and can't reuse a malloced string.

You could copy them to a std::string and immediately delete them, but that will invoke all the behaviours you are trying to avoid.

What you can do is immediately declare a unique_ptr with a custom deleter. When that goes out of scope, it will call the deleter, which will be free(). Meanwhile, you can use it in the same way you would have used the raw pointer.

std::unique_ptr<char, decltype(free)*> RAII(makeAPICall(), free);

In the future you could create an owning wrapper for std::string_view, and perhaps there is advantage in rolling your own in the short term, but unless you have a newer stdlib (c++17) that has replicated all the methods to take string_view I recon it is an exercise in futility.

like image 125
Gem Taylor Avatar answered Oct 19 '22 07:10

Gem Taylor


You cannot use std::basic_string. std::basic_string manages it's own memory so it would allocate new storage and copy the data into the string. You would still have to manually release the storage from the returned pointer.

If you can use C++17 you could use a std::basic_string_view as it will just hold a copy of the pointer, but you run into the same issue where you would need to call the deallocation function manually for the pointer when you are done with it.

What you could do is use a std::unique_ptr or std::shared_ptr with a custom deleter to store the returned pointer from the function so it will automatically reallocate the memmory for you. Then, if you can use C++17 you can get a std::basic_string_view to that pointer so you have all of the string functions without having to make a copy. Otherwise would could just use the c-string function from <cstring> to work with it or write your own version of std::basic_string_view (or find a C++11 library that has one like this one)

like image 4
NathanOliver Avatar answered Oct 19 '22 07:10

NathanOliver