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

Move constructor for std::string from char*

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

The user must delete returned string

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

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

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

std::string(cstring)

避免泄漏。

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

也不负责清理此类缓冲区。

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

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

你从 f() 中得到 std::string

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

如果你能改变f的界面,直接return变成std::string或者std::unique_ptr<char[]>.

另一个好主意是将 f 包装在另一个 return 是 std::unique_ptr<char[]>std::string:

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

and/or

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

std::string 将制作一个空终止字符串参数的副本并管理该副本。没有办法让它拥有您传递给它的字符串的所有权。所以你所做的是正确的,我建议的唯一改进是检查 nullptr,假设这是 f() 的有效 return 值。这是必要的,因为采用 char const *std::string 构造函数要求参数指向有效数组,而不是 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

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

即使您选择第一个选项,我也建议在将 f() 的 return 值传递给 std::string 构造函数之前将其存储在 unique_ptr 中.这样,如果构造失败,returned 字符串仍将被删除。

此代码永远不会正确:

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