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

最后都变了- 提交于 2021-02-07 12:36:33

问题


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..


回答1:


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());


来源:https://stackoverflow.com/questions/29347041/is-there-a-way-to-set-the-length-of-a-stdstring-without-modifying-the-buffer-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!