可以将 char* 移动到 std::string 中吗?

Can a char* be moved into an std::string?

说我有这样的东西

extern "C" void make_foo (char** tgt) {
  *tgt = (char*) malloc(4*sizeof(char));
  strncpy(*tgt, "foo", 4);
}

int main() {
  char* foo;
  make_foo(&foo);
  std::string foos{{foo}};
  free(foo);
  ...
  return 0;
}

现在,我想避免使用然后删除 foo 缓冲区。即,我想将 foos 的初始化更改为

  std::string foos{{std::move(foo)}};

并且不使用显式 free

事实证明这实际上可以编译并且似乎可以工作,但我对此有一种相当怀疑的感觉:它是否真的移动了 C 定义的字符串并正确释放了存储空间?或者它只是忽略 std::move 并在 foo 指针超出范围后泄漏存储?

并不是我太担心额外的副本,而是我确实想知道是否可以用现代移动语义风格来编写它。

std::string constructor #5:

Constructs the string with the contents initialized with a copy of the null-terminated character string pointed to by s. The length of the string is determined by the first null character. The behavior is undefined if s does not point at an array of at least Traits::length(s)+1 elements of CharT, including the case when s is a null pointer.

您的 C 字符串已被复制(std::move 在这里无关紧要)因此您可以在 foo 上调用 free

A std::string 永远不会取得所有权。

tl;dr:不是真的。

指针没有任何特殊的移动语义。 x = std::move(my_char_ptr)x = my_char_ptr 相同。它们在这方面与std::vector相似,其中移动带走了分配的space。

但是,在您的情况下,如果您想保留现有的堆缓冲区并将它们视为字符串 - 它不能使用 std::string,因为它们不能构造为一个现有的缓冲区(还有小字符串优化等)。相反,请考虑实施自定义容器,例如带有一些字符串数据缓冲区 (std::vector<char>) 和一个 std::vector<std::string_view>,其元素指向该缓冲区。