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

时间:2018-06-03 12:23:36

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

说我有类似的东西

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指针超出范围后泄漏存储空间?

并不是我太担心额外的副本,但我想知道是否可以用现代的移动语义风格来写这个。

2 个答案:

答案 0 :(得分:3)

std::string constructor#5:

  

构造字符串,其内容已初始化为,副本为   s指向的以null结尾的字符串。。的长度   字符串由第一个空字符决定。行为是   如果s没有指向至少一个数组,则为undefined   Traits :: length(s)CharT的+1个元素,包括s是a的情况   空指针。

您的C字符串已被复制(此处std::move无关紧要),因此您可以在free上致电foo

std::string永远不会拥有所有权。

答案 1 :(得分:2)

tl; dr:不是。

指针没有任何特殊的移动语义。 x = std::move(my_char_ptr)x = my_char_ptr相同。在这方面,他们 ,例如,std::vector,其中移动会占用分配的空间。

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