4

With the following:

#include <set>

std::set<const char *> global = std::set<const char *>();
void x() {
    const char *c = "a";
    const char *d = "b";

    global.insert(c);
    global.insert(d);
}

int main() {
    x();
    for (std::set<const char *>::const_iterator iter=global.begin(), end=global.end(); iter!=end; ++iter) {
        printf("%s\n", *iter);
    }

    return 0;
}

In the end, as expected, I receive a and b printed.

Yet, is there any guarantee that, for example, if that set was part of a bozo object, that as the set they'd last until the end of bozo's lifetime? Or would I have to strdup the strings to be sure?

Matoe
  • 2,742
  • 6
  • 33
  • 52

1 Answers1

8

You're totally fine because string literals have static storage duration. That is, the string will be around in memory for the duration of the program. However, it would not be okay if you were to have declared your c and d as arrays like so:

const char c[] = "a";
const char d[] = "b";

This is because when an array is initialised with a string literal, the characters from the literal are copied into the array. That array has automatic storage duration, so the contents will be destroyed at the end of the function x. If you still did global.insert(c), you would be pushing in a pointer to the first element of the c array, but that array won't exist for much longer.

Here's some standard quotes. First, §2.14.5/8:

Ordinary string literals and UTF-8 string literals are also referred to as narrow string literals. A narrow string literal has type “array of n const char”, where n is the size of the string as defined below, and has static storage duration (3.7).

And now the definition of static storage duration (§3.7.1/1):

All variables which do not have dynamic storage duration, do not have thread storage duration, and are not local have static storage duration. The storage for these entities shall last for the duration of the program (3.6.2, 3.6.3).

Joseph Mansfield
  • 108,238
  • 20
  • 242
  • 324
  • What about a non-string-literal? (that was just an example) – Matoe Dec 26 '12 at 00:00
  • 1
    The one to watch out for is `char a[] = "c";`, which will go away when the function exits. – Mats Petersson Dec 26 '12 at 00:01
  • @MatsPetersson Yep, I was just on that! – Joseph Mansfield Dec 26 '12 at 00:01
  • 2
    @Matoe How are you going to get a pointer to an integer literal, for example? You can't do `&6` to get the address of the `6` literal because it's an rvalue. – Joseph Mansfield Dec 26 '12 at 00:02
  • I think Mattoe was thinking of "non-literal strings" rather than "non-string literals" - I know, we do like to read literally sometimes as programmers! :) – Mats Petersson Dec 26 '12 at 00:04
  • Exactly. So, basically, way to go is to simply get a pointer (which lasts, on the heap), right? – Matoe Dec 26 '12 at 00:05
  • 3
    Well then I guess the answer is it depends on the lifetime of the `char`s in that string, which depends on how that string was created. String literals are okay here because of their static storage duration. – Joseph Mansfield Dec 26 '12 at 00:07
  • So yeah, this answered the question. Accepting as soon as StackOverflow lets me do so. – Matoe Dec 26 '12 at 00:08
  • 1
    @Matoe The pointer itself has automatic storage duration and will be destroyed at the end of the function, but you're copying that pointer into your container before it has chance to die. The string literal it points to will not die at the end of the function. A string literal is not typically on the heap, but in the data segment of your executable. However, the standard doesn't care much for that. It just says that the string will last for the duration of the program. – Joseph Mansfield Dec 26 '12 at 00:09