我使用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
不能,不能分离std::string::c_str()
返回的指针。
解决方案:创建一个字符串的只读副本,并确保该副本的有效期至少与您需要的char*指针一样长。然后在副本上使用c_str()
,只要你想,它就会有效。
如果这是不可能的,那么你将无法释放char*
。任何试图将该指针包装在RAII结构中的尝试,都只会重新创造std::string的一部分。
std::string
通过std:allocator
(或模板参数)分配。即使您可以分离原始存储,您也必须通过std::allocator
释放它。你当然想要一个RAII类来正确地做到这一点。
std::string
。
因此,最接近"分离"函数的是swap
。它将资源从字符串中分离出来,并将它们存储在稍后可以正确释放的形式中(即另一个字符串)。在c++ 11中,move赋值也会这样做。
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
释放。
使用c_str()
将字符串复制为C样式字符串。然后使用strcpy()
根据您的需要,您可以使用两种方法。string::c_str()将把字符复制到一个C字符串中,然后你可以用它做任何你需要的事情。std::data()将返回一个指向字符串的指针,但有两个问题:a)它不像C字符串那样以NULL结尾,b)当std::字符串被删除时它将消失。所以它不会在你删除原始对象后继续存在
可以将字符串复制到新的char数组中。
std::string s = "My string";
char *a = new char[s.size()+1];
a[s.size()]=0;
memcpy(a,s.c_str(),s.size());
由于您应该始终知道谁拥有特定内存部分,因此更改字符串所有权的唯一方法是复制它。最简单的方法是将字符串赋值给另一个std::string变量。如果所有权变化非常频繁(或者您根本无法清楚地确定哪个特定对象是所有者),您可能希望使用支持引用计数的string的另一种实现(或std::string的包装器),这样您就不必总是分配新的内存。
你可以这样使用:
std::string str = "abcd";
char* cStr = str.c_str();
谢谢…:)