我正在尝试编写一个函数来将std :: string转换为char *。 我写的第一个是:
char* $ (string str)
{
char* cstr;
const unsigned int length=str.size();
cstr=new char[1000];
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
但问题是内存泄漏:让我们假设我这样做:
char* cstr;
string str1("hello"),str2("hello2");
cstr=$(str1);
cstr=$(str2);
在这种情况下存在内存泄漏。第一个分配的字符串不可访问但它的引用丢失。 所以我使用静态做了同样的事情:
char* $ (string str)
{
static char cstr[1000];
const unsigned int length=str.size();
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
但现在问题是可以访问静态字段:
char* cstr;
string str("hello");
cstr=$(str);
$(str)[5]='!';
这是可能的,第6个字符被修改,因此cstr指向的C风格字符串也被修改。
使用const:
const char* $ (string str)
{
static char cstr[1000];
const unsigned int length=str.size();
for(int i=0;i<length;i++)
cstr[i]=str[i];
cstr[length]=0;
return cstr;
}
问题是char指针与const char指针不兼容,所以我不能这样做:
string str("hello");
char* cstr;
cstr=$(str);
但我只能使用const char指针。 我要做的是有一个函数,返回值只能作为右操作数,但不能作为赋值的左操作数。如何做到这一点?
我试着这样做:
char* toCharArray(string& str)
{
std::unique_ptr<char>p(new char[1000]);
char* temp=p.get();
for(unsigned int i=0;i<str.size();i++)
{
*temp=str[i];
temp++;
}
return p.get();
}
但问题仍然存在,我没有看到这个与我使用static发布的其他解决方案之间的区别。因为这样的代码:
char* cstr;
string str("hello");
cstr=toCharArray(str);
toCharArray(str)[0]='o';
cout << cstr;
修改字符串(打印“oello”)。 问题仍未解决。
答案 0 :(得分:2)
您可以将分配的数组作为std::unique_ptr<char[]>
或std::vector<char>
返回,以防止内存泄漏;如果重新分配或超出范围,两者都将释放内存。
您可以分别获得指向char*
或ptr.get()
内容的&vec[0]
指针。
顺便说一下,由于长度已知,因此数组长度确实应为length+1
,而不是1000
。固定大小的缓冲区是等待发生的溢出。此外,$
不是函数的可移植名称。
答案 1 :(得分:1)
您需要创建一个新的char *
并将std::string
的内容复制到其上。
您可以使用strcpy。
答案 2 :(得分:1)
http://www.cplusplus.com/reference/string/string/c_str/
看一下这个例子,具体来说:
char * cstr, *p;
string str ("Please split this phrase into tokens");
cstr = new char [str.size()+1];
strcpy (cstr, str.c_str());
答案 3 :(得分:0)
我不明白为什么你对内存泄漏感到惊讶。如果你要复制一些东西,你必须把它放在某个地方。
您可以将所有副本放在同一个地方(冒着溢出的风险,并承担在客户端上获取正确副本的责任,或者他们冒着意外损坏的风险),或者您进行分配(他们仍然需要进行释放,但至少他们不需要复制),或者让他们将缓冲区和大小传递给你的函数。
严肃地说,$作为一个函数名?
答案 4 :(得分:-3)
str.c_str()
怎么样?或strdup(str.c_str())
如果您想要副本。