7

I know that string literals in C/C++ have static storage duration, meaning that they live "forever", i.e. as long as the program runs.

Thus, if I have a function that is being called very frequently and uses a string literal like so:

void foo(int val)
{
    std::stringstream s;
    s << val;
    lbl->set_label("Value: " + s.str());
}

where the set_label function takes a const std::string& as a parameter.

Should I be using a const std::string here instead of the string literal or would it make no difference?

I need to minimise as much runtime memory consumption as possible.

edit:

I meant to compare the string literal with a const std::string prefix("Value: "); that is initialized in some sort of a constants header file.

Also, the concatenation here returns a temporary (let us call it Value: 42 and a const reference to this temporary is being passed to the function set_text(), am I correct in this?

Thank you again!

Victor Parmar
  • 5,719
  • 6
  • 33
  • 36
  • What's your magic 8 ball say? – Edward Strange Dec 05 '10 at 22:59
  • If you want to minimize runtime memory consumption, how about modifying set_label to take a const char * and use a char * instead of a string? – user347594 Dec 05 '10 at 23:02
  • @user347594: I can't modify `set_label` unfortunately – Victor Parmar Dec 05 '10 at 23:07
  • @Noah: Having a const string would greatly increase the maintainability of the code, but I will sacrifice that for memory optimizations for this application, hence my question =) – Victor Parmar Dec 05 '10 at 23:13
  • Since you say this function is being called very frequently, you probably don't want to use `stringstream`, which is very VERY slow. See http://stackoverflow.com/questions/4351371/c-performance-challenge-integer-to-stdstring-conversion. – Ben Voigt Dec 05 '10 at 23:14
  • Besides, `stringstream` (along with `stringbuf` and all the other support machinery) is waaaay more of a memory hog than the difference between `char*` and `std::string`. – Ben Voigt Dec 06 '10 at 00:02

4 Answers4

9

Your program operates on the same literal every time. There is no more efficient form of storage. A std::string would be constructed, duplicated on the heap, then freed every time the function runs, which would be a total waste.

Puppy
  • 144,682
  • 38
  • 256
  • 465
  • 6
    Unless you know what implementation the OP's using, you can't know that this isn't exactly what's happening anyway nor that compiler optimizations won't render your statement completely false. – Edward Strange Dec 05 '10 at 23:03
  • 1
    Noah is right, a small string like this may not use heap storage at all. `stringstream` on the other hand is very heavyweight... – Ben Voigt Dec 06 '10 at 02:45
  • @Noah: I'm quite sure that no matter how the compiler optimizes, it can't come up with something more efficient than a literal string. – Puppy Dec 06 '10 at 12:04
  • @DeadMG would using a string literal be better than using a `const std::string` defined in a constants header file or does it make no difference? – Victor Parmar Dec 06 '10 at 16:23
  • @vic: It really doesn't matter. A string literal is statically allocated once and referred to forever after. There is no possible way of storing that data in a more efficient fashion, end of story. – Puppy Dec 06 '10 at 18:08
  • @DeadMG: No there's no more efficient storage for the character data, but you need to use templates to access that string literal efficiently. If you let it decay to a `const char*`, then finding the length becomes O(N), while getting the length of a `std::string` is O(1). – Ben Voigt Dec 06 '10 at 22:14
  • @Ben: I know. The OP specified runtime memory usage, so I really don't care. – Puppy Dec 06 '10 at 22:44
  • @DeadMG: Yeah, some of the reply comments say "performant" or "efficiency" but the question only asks to "minimize memory consumption". OTOH, a string literal passed to `operator+(const std::string&, const std::string&)`, as is done here, will use no less memory than a reference to a global `std::string`. – Ben Voigt Dec 06 '10 at 22:48
  • @Ben: Doesn't std::string have operator+ overloads for const char*? As for efficiency, there is memory efficiency as well as time efficiency. – Puppy Dec 06 '10 at 23:51
  • @DeadMG: You're right of course, the code in the question would call `operator+(const char*, std::string&)`, but since that can't infer the length like a template could, it has to measure it, which at least temporarily uses more memory than a `std::string`. The difference in memory usage is so minuscule either way that I tend to move directly to speed concerns. – Ben Voigt Dec 06 '10 at 23:59
  • @Ben: Me too. There's no `template operator+(const char(&)[size], const std::string&)`? That seems an unnecessary oversight. – Puppy Dec 07 '10 at 10:59
  • @DeadMG: That's exactly what I was talking about... and it appears that there isn't even a `std::string` constructor that accepts a character array like that, nor is one added in C++0x (not sure whether `initializer_list` gives the same advantages). It would seem that the performance of `operator+` could be increased considerably by providing a constructor that accepts an array by reference, and an additional parameter which is the size to reserve so that the call to `append` won't cause reallocation. – Ben Voigt Dec 07 '10 at 13:58
2

This will use less memory and run much faster (use snprintf if your compiler supports it):

void foo(int val)
{
    char msg[32];
    lbl->set_label(std::string(msg, sprintf(msg, "Value: %d", val)));
}

For even faster implementations, check out C++ performance challenge: integer to std::string conversion

Ben Voigt
  • 277,958
  • 43
  • 419
  • 720
  • +1 for the optimization! Coming back to my original question though, would a string literal be more perfomant than using a `const std::string` defined in a constants header file? – Victor Parmar Dec 06 '10 at 16:25
  • @vic: It really depends whether you need the length. `std::string` caches the length, so it's a small matter of reading a variable, while with a `char*` you have to use `strlen` which iterates. However, the string literal itself is a character array which carries its length as part of the compile-time type information, which is the fastest of all (when the code is written to take advantage of it). – Ben Voigt Dec 06 '10 at 17:35
  • You missed a parenthesis in your answer. +1 anyway. I like the solution. – whoan Jan 11 '18 at 12:29
  • @whoan: Thanks for bringing that to my attention. – Ben Voigt Jan 11 '18 at 15:29
0

How will you build your const std::string ? If you do it from some string literral, in the end it will just be worse (or identical if compiler does a good job). A string literal does not consumes much memory, and also static memory, that may not be the kind of memory you are low of.

If you can read all your string literals from, say a file, and give the memory back to OS when the strings are not used any more, there may be some way to reduce memory footprint (but it will probably slow the program much).

But there is probably many other ways to reduce memory consumption before doing that kind of thing.

kriss
  • 23,497
  • 17
  • 97
  • 116
0

Store them in some kind of resource and load/unload them as necessary.

engf-010
  • 3,980
  • 1
  • 14
  • 25