我们可以用std::string交换char*吗

Can we swap char* with std::string

本文关键字:交换 char string 我们 std      更新时间:2023-10-16

修改std::string::op[]的结果合法吗?

我想交换char*和std::string的内容,但无法完成。经过上面的链接,我仍然无法得到问题的答案。

这就是我正在尝试做的,但无法成功地用char*交换字符串。该代码已在VS2010上验证。

更新1所有的努力都是看看我是否能获得任何性能而不获得任何SO分数。:-)
更新2我在评论中提到了我打算这么做的原因。人们还认为这需要暂停吗?

void Swap(char* const& left, char* const& right)
{
    std::swap(const_cast<char*>(left), const_cast<char*>(right));
}

std::string ToString()
{
   std::string ret(1, ' ');
   char* str = new char[6]();
   strcpy(str, "Jagan");
   Swap(&ret[0], str);
    return ret;
}

无法完成。

std::string没有为您提供替换其内部数据指针的标准方法。

事实上,并不是所有std::string的实现都总是有一个指向使用new[]分配的零终止字符块的指针。你不应该知道,如果你发现了,当然也不应该依赖它(信息隐藏/实现隐藏)。

不同的std::string实现可能会执行以下任何操作:

  • 保持大小与非零端接的CCD_ 5分开。除了经典的C字符串之外,std::string的实例还允许包含null字符
  • 但在具有参考计数的不同std::strings之间共享。你不想干涉这里
  • 具有一个分配给char [16]的堆栈,该堆栈用于短字符串,而不是堆指针

这就是为什么当你想与自己管理的char*交换时,你不得不复制std::string内容

代码&ret[0]所做的只是创建一个临时变量,该变量是指向ret中字符的指针。对swap的调用将该临时变量设置为指针str,并将str设置为该临时变量。结果是ret不受影响,并且您泄漏了str中的内存。为了更清楚,这个代码相当于

char* str = new char[6]();
strcpy(str, "Jagan");
char* tmpPtr = &ret[0]
Swap(tmpPtr, str);

所以你可以在它的末尾看到tmpPtr等于str的原始值。您根本无法访问str中的内部char*指针。这是深思熟虑的,因为更广泛的问题是你为什么要这样做即使您可以分配给str的内部指针,这样做也会违反封装——例如,您假设内部指针是使用new分配的。但是stl容器可以——而且确实——使用它们自己的内部分配机制,并且在未来应该可以自由地更改它们的实现,而不会破坏客户端代码。正如您可以在不破坏客户端代码的情况下更改类的实现一样。

是的,正如您在链接的文章中所看到的,如果x >= 0 && x < string.size(),您可以修改string[x]的值,但标准很清楚,您不能修改任何其他内容(当然也不能将&string[x]作为可修改的空终止字符串的有效指针传递——记住string.c_str()string.data()返回一个const char*

然而,您可以实现:

void swap(std::string& left, char* right) {
  auto right_size = std::strlen(right);
  auto left_size = left.size();
  assert(left_size <= right_size);
  std::string temp = std::move(left);
  left = right;
  std::copy(std::begin(temp), std::end(temp), right);
  right[left_size] = '';
}
inline void swap(char* left, std::string& right) {
  swap(right, left);
}

(住在这里)

你所做的在很多层面上都是错误的。

要用char *指向的手动管理字符串"交换"std::string,您需要手动管理该字符串,如:

std::string one = ...;
char *two = ...;
// swap:
std::string tmp = two;
delete[] two;
two = new char[one.size() + 1];
memcpy(two, one.c_str(), one.size() + 1);
one = tmp;