C ++:是否可以从std :: string对象中分离char *指针?

时间:2012-01-02 09:29:17

标签: c++ string

我正在使用std :: string类型进行字符串操作。

然而,有时我需要保留原始的char *指针,即使在原始的std :: string对象被销毁之后(是的,我知道char *指针引用了HEAP并且最终必须被处理掉)。

但是,看起来没有办法从字符串中分离原始指针或是吗?

也许我应该使用另一个字符串实现?

感谢。

修改

伙计们,请不要将分离与复制混淆。分离的本质是字符串对象放弃其对底层缓冲区的所有权。因此,如果字符串具有detach方法,则其语义将是这样的:

char *ptr = NULL;
{
  std::string s = "Hello world!";
  ptr = s.detach(); // May actually allocate memory, if the string is small enough to have been held inside the static buffer found in std::string.
  assert(s == NULL);
}
// at this point s is destroyed
// ptr continues to point to a valid HEAP memory with the "Hello world!" string in it.
...
delete ptr; // need to cleanup

7 个答案:

答案 0 :(得分:5)

不,不能分离std::string::c_str()返回的指针。

解决方案:创建字符串的只读副本,并确保该副本至少与您需要char *指针一样长。然后在该副本上使用c_str(),只要您愿意,它就会有效。

如果无法做到,那么您将无法释放char*。任何将指针包装在RAII结构中的尝试都只会重新发明std :: string的部分内容。

答案 1 :(得分:4)

std::string通过std:allocator(或模板参数)进行分配。即使你可以分离原始存储,你也必须通过std::allocator释放它。你当然希望RAII课程能够正确地做到这一点。

幸运的是,标准库中已经存在这样的RAII类。它被称为std::string

因此,与“分离”功能最接近的是swap。它将资源与字符串分离,并将它们存储在以后可以正确释放它们的形式(即另一个字符串)中。在C ++ 11中,移动赋值也是如此。

std::string raii_for_ptr;
const char *ptr = NULL;
{
     std::string s = "Hello world!";
     raii_for_ptr.swap(s); // or raii_for_ptr = std::move(s)
     ptr = raii_for_ptr.c_str();
     assert(s == "");
}

// no need to cleanup

如果您的目标是为自己创建需要在某事上调用delete,那么(a)这是荒谬的,因此(b)标准库将无法帮助您。无论如何,您可能需要delete[]而不是delete。但由于字符串不是(直接)用new分配的,所以认为你可以记住它并(直接)用delete[]释放它是不恰当的。

所以,如果你的真实情况是你需要传递一些预先存在的API,一个将被delete[]释放的缓冲区,那么你将需要复制一份,就好像你需要传递一样一些预先存在的API,将使用free释放缓冲区。

答案 2 :(得分:1)

使用c_str()将字符串复制到C样式字符串中。然后使用strcpy()

答案 3 :(得分:1)

您可以将字符串复制到新的char数组。

std::string s = "My string";
char *a = new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());

答案 4 :(得分:0)

根据您的需要,您可以使用两件事。 string :: c_str()会将字符复制到C字符串中,然后可以根据需要使用它。 std :: data()将返回一个指向字符串的指针,但是有两个问题:a)它不像C字符串那样以NULL结尾,而b)当删除std :: string时它会消失。因此,在删除原始对象后,它不会留下来。

答案 5 :(得分:0)

由于您应该始终知道谁拥有特定的内存部分,因此更改字符串所有权的唯一方法是复制它。最简单的方法是将字符串分配给另一个std :: string变量。如果所有权经常更改(或者您根本无法清楚地确定哪个特定对象是所有者),您将需要使用另一个支持引用计数的字符串实现(或std :: string包装器),因此您不需要必须一直分配新的记忆。

答案 6 :(得分:0)

你可以按如下方式使用它:

std::string str = "abcd";
char* cStr = str.c_str();

...谢谢:)