简体   繁体   中英

Behavior when fetching const ptr from string stringstream

I have the following piece of code, for which i am trying to understand its behavior :

#include <iostream>
#include <vector>
#include <string>
#include <sstream>

using namespace std;

void fill(std::vector<const char *> & vec, string str) {
   uint32_t start_count = 1;
   stringstream regname;
   for(uint32_t count = 0; count <= 3; count++) {
      regname.str("");
      regname << str << (uint32_t)(count + start_count);
      std::cout << "regname : " << regname.str() << std::endl;
      vec.push_back(regname.str().c_str());
   }
}

int main() {
   vector<const char *> vec;
   fill(vec, "temp");

   for(int i = 0; i < vec.size(); i++)
      std::cout << "value at index : " << i << " is  : " << vec[i] << std::endl;
   return 0;
}

Initial string in the vector are printed correctly, however for strings initialized in fill method i get all the instances with "temp4" which is the last initialized string. O/P when using std::vector of const char * :

regname : temp1
regname : temp2
regname : temp3
regname : temp4
value at index : 0 is  : temp4
value at index : 1 is  : temp4
value at index : 2 is  : temp4
value at index : 3 is  : temp4

This behavior is corrected when i try to use std::vector instead. O/P when using std::vector of string object :

regname : temp1
regname : temp2
regname : temp3
regname : temp4
value at index : 0 is  : temp1
value at index : 1 is  : temp2
value at index : 2 is  : temp3
value at index : 3 is  : temp4

Just wanted to know what is causing this behavior ?

Calling str on regname will return a string copy of the streams contents. Calling c_str on that string will return a pointer to an array that contains the sequence of characters in that string.

Apparently, the pointer you push back to this array is the same for all 4 loop iterations and printing them after calling the fill method will print the same contents four times.

Your current code is unsafe as the strings are temporaries within your fill method and the pointers to their internal character arrays will dangle after returning from fill . Better use strings in you vec vector to store real copies.

Before push_back() , allocate memory dynamically to preserve it after function's callframe is cleared. Something like below (See http://ideone.com/aR0f98 demo)

#include <cstring>

...
char * p = new char[regname.str().length() + 1];
strcpy(p, regname.str().c_str());
vec.push_back(p);

Remember to delete it after it is used to prevent memory leaks. However, this is NOT recommended. Use of std::string is recommended here.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM