Search code examples
c++staticobject-lifetime

Is it safe to store string literals pointers?


According to the standard:

5.13.5 String literals [lex.string]

16 Evaluating a string-literal results in a string literal object with static storage duration, initialized from the given characters as specified above. Whether all string literals are distinct (that is, are stored in nonoverlapping objects) and whether successive evaluations of a string-literal yield the same or a different object is unspecified.

and:

6.6.4.1 Static storage duration [basic.stc.static]

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

I assume it's safe to store pointers to string literals, something like:

struct Base
{
    Base(const char* name)
        : _name(name)
    {
    }
    
    void print()
    {
        std::cout<<_name<<std::endl;
    }
    
    const char* _name = nullptr;
};

struct MyDerived : public Base
{
    MyDerived () : Base("MyDerived")
    {
    }
};

Is the above code well defined? Are there any dark corners of standard that I have to be aware of?


Solution

  • Is the above code well defined?

    Yes.

    Are there any dark corners of standard that I have to be aware of?

    Perhaps not a dark corner in the standard but one problem is that you have a pointer and you allow for Base to be instantiated and used like this:

    Base foo(nullptr);
    foo.print();
    

    From operator<<: "The behavior is undefined if s is a null pointer."

    A somewhat safer constructor:

    template<size_t N>
    constexpr Base(const char(&name)[N]) : _name(name) {}
    

    I say somewhat because you still can do this:

    auto Foo() {
        const char scoped[] = "Fragile";
        Base foo(scoped);
        foo.print();     // OK
        return foo;
    }                    // "scoped" goes out of scope, "_name" is now dangling
    
    int main() {
        auto f = Foo();
        f.print();       // UB
    }