从char *移动std :: string的构造函数

时间:2015-02-23 18:35:35

标签: c++ string c++11 move-semantics

我有一个函数f返回char*。功能文档说:

The user must delete returned string

我想从中构建一个std::string。琐碎的事情是:

char* cstring = f();
std::string s(cstring);
delete cstring;

使用C ++功能可以做得更好吗?我想写点像

std::string(cstring)

避免泄漏。

4 个答案:

答案 0 :(得分:8)

std::string将复制空终止字符串参数并管理该副本。没有办法让它获得你传递给它的字符串的所有权。所以你所做的是正确的,我建议的唯一改进就是检查nullptr,假设它是f()的有效返回值。这是必要的,因为std::string构造函数采用char const *要求参数指向有效数组,而不是nullptr

char* cstring = f();
std::string s(cstring ? cstring : "");
delete[] cstring;   // You most likely want delete[] and not delete

现在,如果您不需要所有std::string的界面,或者如果避免副本很重要,那么您可以使用unique_ptr来管理字符串。

std::unique_ptr<char[]> s{f()}; // will call delete[] automatically

您可以通过char *访问托管s.get(),当delete超出范围时,字符串将为s

即使您使用第一个选项,我建议将f()的返回值存储在unique_ptr中,然后再将其传递给std::string构造函数。这样,如果构造抛出,返回的字符串仍将被删除。

答案 1 :(得分:2)

std::string没有标准方法来获取您传递的缓冲区的所有权。

也不负责清理这样的缓冲区。

理论上,一个实现,知道所有内部细节,可以std::string添加一种方式来接管分配器分配的缓冲区,但我不知道任何实施的 也没有任何保证这样做实际上是有利的,具体取决于实施细节。

答案 2 :(得分:1)

此代码永远不会是正确的:

std::string s(cstring);
delete cstring;

带有字符指针的std::string构造函数需要一个以NUL结尾的字符串。所以它是多个字符。

delete cstring是标量删除。

您是否尝试从字符标量创建字符串(在这种情况下,为什么是间接?)

std::string s(cstring[0]);
delete cstring;

或者您有多个字符,应相应删除

std::string s(cstring);
delete [] cstring;

检查其他答案,了解建议的方法,以确保delete[]被使用,例如

std::string(std::unique_ptr<char[]>(f()).get())

答案 3 :(得分:0)

std::string steal_char_buffer( std::unique_ptr<char[]> buff ) {
  std::string s = buff?buff.get():""; // handle null pointers
  return s;
}
std::string steal_char_buffer( const char* str ) {
  std::unique_ptr<char[]> buff(str); // manage lifetime
  return steal_char_buffer(std::move(buff));
}

现在您可以输入

std::string s = steal_char_buffer(f());

,您从std::string中获得f()

可能想要使steal_char_buffer的参数成为const char*&&。它几乎没有意义,但可能会导致一些有用的错误。

如果您可以更改f的界面,请直接返回std::stringstd::unique_ptr<char[]>

另一个好主意是将f包装在另一个返回std::unique_ptr<char[]>std::string的函数中:

std::unique_ptr<char[]> good_f() {
  return std::unique_ptr<char[]>(f());
}

和/或

std::string good_f2() {
  auto s = good_f();
  return steal_char_buffer( std::move(s) );
}