Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to reserve and copy into a std::string directly?

Is it possible to reserve space in a std::string and get a pointer to copy char data directly into it? I have to interface with a C library that returns strings by copying them into a char *. How can I set up a std::string so that the library can write directly into it, avoiding intermediate copies.

Hypothetical example how this could look like:

std::string mystring;
int strlen = foolib_get_string_size(fooval);
mystring.size(strlen); // assuming size() with arg exists and does reserve() and set size
foolib_string_to_char_buffer(fooval, mystring.data(), strlen); // abusing data() method for writing
like image 600
diemo Avatar asked Oct 26 '25 08:10

diemo


1 Answers

Is it possible to reserve space in a std::string and get a pointer to copy char data directly into it?

Yes. Use its resize() method to allocate the memory, and then use its data() method (C++17 and later), or its operator[], to access that memory.

I have to interface with a C library that returns strings by copying them into a char *. How can I set up a std::string so that the library can write directly into it, avoiding intermediate copies.

Like this:

std::string mystring;
int strlen = foolib_get_string_size(fooval);
if (strlen > 0)
{
    mystring.resize(strlen); // -1 if strlen includes space for a null terminator
    foolib_string_to_char_buffer(fooval, mystring.data()/*&mystring[0]*/, strlen);
}

Alternatively, std::string has constructors which can allocate memory, too:

int strlen = foolib_get_string_size(fooval);
std::string mystring(strlen, '\0'); // -1 if strlen includes space for a null terminator
if (strlen > 0)
    foolib_string_to_char_buffer(fooval, mystring.data()/*&mystring[0]*/, strlen);

Of course, this does require std::string's memory block to be allocated contiguously, which is only guaranteed in C++11 and later (but in practice, is done in just about all known implementations). If you are not using C++11 or later, and really want to be standards compliant, then you should use an intermediate buffer, such as a std::vector, eg:

std::string mystring;
int strlen = foolib_get_string_size(fooval);
if (strlen > 0)
{
    std::vector<char> myvector(strlen);
    foolib_string_to_char_buffer(fooval, &myvec[0], strlen);
    mystring.assign(&myvec[0], strlen); // -1 if strlen includes space for a null terminator
}
like image 200
Remy Lebeau Avatar answered Oct 29 '25 01:10

Remy Lebeau



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!