0

Is the following code considered safe?

Foo& GetFoo()
{
    static std::once_flag fooInitFlag;
    static Foo f;

    std::call_once(fooInitFlag, [&Foo]()
    {
       Foo.Init();
    });

    return std::ref(f);

}
3
  • 5
    You don't need the once_flag thing. A single initialization is guaranteed. Use constructor, not Init method- Commented May 21, 2015 at 17:17
  • Yes. Note you still need that in msvc 2013 but not in C++11 conform compiler where static initialization is thread safe. (do not return std::ref(f), just f) Commented May 21, 2015 at 17:18
  • 1
    You don't need std::ref here; just return f. And it's safe, since f will remain. Commented May 21, 2015 at 17:19

2 Answers 2

3

Instead of this posted code:

Foo& GetFoo()
{
    static std::once_flag fooInitFlag;
    static Foo f;

    std::call_once(fooInitFlag, [&Foo]()
    {
       Foo.Init();
    });

    return std::ref(f);
}

do this:

struct Initialized_foo
{
    Foo item;
    Initialized_foo() { item.Init(); }
};

auto get_foo()
    -> Foo&
{
    static Initialized_foo the_foo;
    return the_foo.item;
}

It's not more safe, but it's simpler, and hence more safe against inadvertently introduced bugs.

Note that the standard guarantees a single initialization here, even in the context of multi-threading.


Better, ideally each Foo insteance should be properly initialized by the Foo constructor, not by an Init method. But that's not always possible to arrange.

Sign up to request clarification or add additional context in comments.

4 Comments

You forgot the_foo.item
And static Initialized_foo the_foo;.
@RSahu: thanks, again. hm. maybe should turn off the TV.
@tom: I reverted your pure coding style edit. Please don't do that. No need for braces wars and all that.
2

You asked:

Is the following code considered safe?

The answer is yes.

Another implementation:

// Not exposed to the outside.
static Foo& getInitializedFoo();
{
    static Foo f;
    f.Init();
    return f;
}

Foo& GetFoo()
{
    static Foo& f = getInitializedFoo();
    return f;
}

4 Comments

how about, static Foo& (reference), to avoid the copying. I think it's just a typo.
@Cheersandhth.-Alf, I meant the helper function to return an object by value.
Well, it would work just as well with a reference (same initialization guarantee), static Foo, and more efficient + less chance of side-effect. Downside that getInitializedFoo then is an internal implementation detail, to only be called once.
@Cheersandhth.-Alf, I see.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.