如何直接从char*数组创建std::string而无需复制?

22

假设我有一个字符数组,已经在堆上进行了分配,并且我想将其转换为std::string。目前我正在执行以下操作:

char *array = new char[size];
WriteIntoArray(array, size);
std::string mystring(array);
delete[] array;
return mystring; // or whatever
根据我从互联网上所读到的(http://www.cplusplus.com/reference/string/string/string/),字符串构造函数会复制我传递给它的缓冲区,我需要手动释放这个缓冲区(稍后,string对象会释放它内部的缓冲区)。我想做的是分配一个缓冲区,将其控制权转移给字符串,然后在字符串被销毁时让它释放我的缓冲区。
这个问题初始化char*指针的std::string不进行复制看起来很有前途,但我的代码依赖于API调用(如上面例子中的“WriteIntoArray”),必须写入一个字符数组,因此我必须创建一个C风格的char*缓冲区,并且无法将我的代码转换为只使用内置的字符串操作(这是建议的答案)。
有没有一些标准的方法可以做到这一点,或者我应该编写自己的字符串类(呃)?谢谢!
3个回答

19
如果您正在使用符合C++0x标准的实现方式,或者使用保证std::string具有连续存储特性的众多C++库之一,则可以获得指向std::string所使用存储的char*

例如:

std::string mystring;
mystring.resize(size);
WriteIntoArray(&mystring[0], size);
return mystring;

不过,您可能需要仔细考虑空终止符。


1
reserve()函数可以预留空间,但是它并不属于字符串(至少目前还不属于)。访问a[0]或a[1]仍然是未定义的行为。如果你检查size(),它仍然是零。你实际想要的是resize()函数。 - Martin York
2
你不能使用reserve(),必须使用resize()。然后在调用之后找出一个合适的resize()。 - Bo Persson
2
“reserve” 需要改为 “resize”。 “认真思考空终止符” 究竟意味着什么?是否有保证,&mystring[0]指向的数组必须以空终止符结尾? std::string 是否负责确保存在此类终止符?如果 WriteIntoArray 写入空终止符,应该将其删除吗?(我问这个问题是因为我不知道 std::string 保证和要求什么。) - James McNellis
2
假设 WriteIntoArray 放置了一个空终止符,这需要在调用后删除;你可能想在返回之前添加 mystring.resize(size-1);。如果它没有添加空终止符,那么你应该使用 vector<char> 而不是 string - Mark Ransom
3
是的,在C++11中是允许的。关于这个问题有很多晦涩难懂的措辞,但基本上归结为不允许修改空终止符,并且不能通过data()或c_str()指针修改任何内容,但通过&str[0]是合法的。https://dev59.com/FmYq5IYBdhLWcg3wridD#14291203 - John Calsbeek
显示剩余9条评论

12

很棒的想法,完全忘记了分配器。 - fyhuang

6

您不能使用std::string拥有指针,因此它会将数据复制到它分配的空间中。

您可以这样做:

std::string  mystring(size, ' ');
WriteIntoArray(&mystring[0], size);
return mystring; // or whatever

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接