Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

is there a way to set the length of a std::string without modifying the buffer content?

According to the statements made in the answers of these questions

  • Is writing to &str[0] buffer (of a std:string) well-defined behaviour in C++11?
  • Is it legal to write to std::string?
  • writing directly to std::string internal buffers

.. in C++11 it should be possible to call a C API function which takes a char pointer to store the output like this:

str::string str;
str.reserve(SOME_MAX_VALUE);
some_C_API_func(&str[0]);

But is there now a legal way to set the size of the string to the length of the (null terminated) content inside the buffer? Something like this:

str.set_size(strlen(&str[0]));

This is a very unaesthetic abuse of std::string anyway I hear you say, but I can't create a temporary char buffer on stack so I would have to create a buffer in heap and destroy it afterwards (which I want to avoid).

Is there a nice way to do this? Maybe not reserving but resizing and calling erase() afterwards would do it but it doesn't feel nice neater..

like image 678
frans Avatar asked Mar 30 '15 13:03

frans


People also ask

Can we change the length of string?

No, the std::string class is designed to manage the memory occupied by the underlying char array dynamically (and thus changing it's length).


1 Answers

You should be using resize() not reserve(), then resize() again to set the final length.

Otherwise when you resize() from zero to the result returned by strlen() the array will be filled with zero characters, overwriting what you wrote into it. The string is allowed to do that, because it (correctly) assumes that everything from the current size to the current reserved capacity is uninitialized data that doesn't contain anything.

In order for the string to know that the characters are actually valid and their contents should be preserved, you need to use resize() initially, not reserve(). Then when you resize() again to make the string smaller it only truncates the unwanted end of the string and adds a null terminator, it won't overwrite what you wrote into it.

N.B. the initial resize() will zero-fill the string, which is not strictly necessary in your case because you're going to overwrite the portion you care about and then discard the rest anyway. If the strings are very long and profiling shows the zero-filling is a problem then you could do this instead:

std::unique_ptr<char[]> str(new char[SOME_MAX_VALUE]);
some_C_API_func(str.get());
like image 195
Jonathan Wakely Avatar answered Oct 20 '22 00:10

Jonathan Wakely