Home > OS >  String allocation problem on each iteration
String allocation problem on each iteration

Time:01-11

l have a string like "hello_1_world". And in each iteration l want to increment "1" part. "hello_2_world", "hello_3_world" etc... So l can not use const char* or string_view. l have to allocate new memory in every iteration by using std::string. But, l do not want to because of performance issue. Could you suggest a solution?

So, my code is like below. Guess index is incrementing each time.

std::string value{"hello_"   std::to_string(index)   "_world"};

l tried so many ways. And one of them is like below:

string_view result(value, 39);

And concat something but again. l cant modify string_view

CodePudding user response:

Do you really need a std::string, or will a simple char[] suffice? If so, then try something like this:

// a 32bit positive int takes up 10 digits max...
const int MAX_DIGITS = 10;
char value[6   MAX_DIGITS   6   1];

for(int index = 0; index < ...;   index) {
    std::snprintf(value, std::size(value), "hello_%d_world", index);
    // use value as needed...
}

Alternatively, if you don't mind having leading zeros in the number, then you can update just that portion of the buffer on each iteration:

const int MAX_DIGITS = ...; // whatever you need, up to 10 max
char value[6   MAX_DIGITS   6   1];

std::strcpy(value, "hello_");
std::strcpy(&value[6   MAX_DIGITS], "_world");

for(int index = 0; index < ...;   index) {
    std::snprintf(&value[6], MAX_DIGITS, "%0.*d", MAX_DIGITS, index);
    // use value as needed...
}

If you really need a std::string, then simply pre-allocate it before the iteration, and then fill in its existing memory during the iteration, similar to a char[]:

const int MAX_DIGITS = 10;

std::string value;
value.reserve(6   MAX_DIGITS   6); // allocate capacity

for(int index = 0; index < ...;   index) {
    value.resize(value.capacity()); // preset size, no allocation when newsize <= capacity

    std::copy_n("hello_", 6, value.begin());

    auto ptr = std::to_chars(&value[6], &value[6   MAX_DIGITS], index).ptr;
    /* or:
    auto numWritten = std::snprintf(&value[6], MAX_DIGITS, "%d", index);
    auto ptr = &value[6   numWritten];
    */

    auto newEnd = std::copy_n("_world", 6, ptr);

    value.resize(newEnd - value.data()); // no allocation when shrinking size

    // use value as needed...
}

Alternatively, with leading zeros:

const int MAX_DIGITS = ...; // up to 10 max

std::string value(6   MAX_DIGITS   6, '\0');

std::copy_n("hello_", 6, value.begin());
std::copy_n("_world", 6, &value[6   MAX_DIGITS]);

for(int index = 0; index < ...;   index) {
    std::snprintf(&value[6], MAX_DIGITS, "%0.*d", MAX_DIGITS, index);
    // use value as needed...
}

CodePudding user response:

you could use a std::stringstream to construct the string incrementally:

std::stringstream ss;
ss << "hello_";
ss << index;
ss << "_world";
std::string value = ss.str();
  •  Tags:  
  • c
  • Related