代码之家  ›  专栏  ›  技术社区  ›  leftaroundabout

一个字符可以移动到STD::字符串吗?

  •  3
  • leftaroundabout  · 技术社区  · 7 年前

    说我有这样的东西

    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 一旦 指针超出范围?

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

    2 回复  |  直到 7 年前
        1
  •  2
  •   einpoklum    7 年前

    TL;博士:不是真的。

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

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

        2
  •  3
  •   Hatted Rooster    7 年前

    std::string constructor 第5类:

    用初始化的内容构造字符串 一份副本 s指向的以空结尾的字符串。 长度 字符串由第一个空字符确定。行为是 如果s不指向 traits::长度+1个图表元素,包括s是 空指针。

    你的c字符串被复制 std::move 在这里没关系)因此你可以打电话给 free foo

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