I'm writing a C++ program that uses the RRD libraries that require an array of 'const char*' for their functions. I thought I could just declare the array, and then initialize each element of the array, but changing one, changes all of them. Obviously I'm missing something. Here's an example similar to the code I am writing (ie it exhibits the same problem).
string intToString(long i)
{
stringstream ss;
string s;
ss << i;
s = ss.str();
return s;
}
int main(){
const char* av[5];
int i = 0;
int j = 0;
for(i=0;i<5;i++){
j= 0;
av[i] = intToString(i).c_str();
for(j=0;j<5;j++){ cout << j << " : " << av[j] << endl;}
}
}
Any help would be appreciated.
The const char*
returned by the c_str()
method of a std::string
points to a buffer owned by the std::string
and only remains valid until the next call to a mutating method of the std::string
. If you want to retain the contents of this buffer, you need to copy its contents somewhere else.
Edit: Alternatively, you could retain an array of std::string
to manage the storage of the strings and temporarily store the c_str()
pointers in a parallel array of const char*
as required for the interface. This obviates the need to copy the strings or manually deallocate the copies. In any case, it's important to not change any std::string
while you are holding the const char*
value returned by a prior call to c_str()
.
string::c_str
returns temporary pointer. You could use strdup
to get persistent pointer.
// don't forget to release memory later
av[i] = strdup( intToString(i).c_str(); );
Or you could allocate all buffers manually and then use string::copy
to copy string data.
Bringing everything together, you can write your program like this:
#include <sstream>
#include <iostream>
std::string intToString(long i)
{
std::stringstream ss;
std::string s;
ss << i;
s = ss.str();
return s;
}
int main(){
const char* av[5]; // declared but not initialised
std::string sav[5]; // std::string has a ctor, so they're initialised
for(int i=0;i<5;i++){
av[i]=""; // initialise each const char*
}
for(int i=0;i<5;i++){
sav[i] = intToString(i); // Keep the original in sav[]
av[i] = sav[i].c_str(); // point to each string's contents
for(int j=0;j<5;j++){ std::cout << j << " : " << av[j] << std::endl;}
}
}
@Philip: Note that your program prints every av[]
after each av[]
is re-initialised.
Note that memory management is handled by sav[]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.