Is it correct to define a global std::string in a header file like this :
namespace Colors
{
static const std::string s_blue = "Blue";
}
Is it correct to define a global std::string in a header file like this :
namespace Colors
{
static const std::string s_blue = "Blue";
}
Yes. static
here means that each translation unit (TU) that includes this header will have a unique object. So there isn't 1 s_blue
object for the whole project, but one for each TU.
However since it's const
all objects will be equal, so for the user it doesn't make a difference.
Maybe, depends.
The big downside is that you create multiple objects and all of them are initialized at program startup.
Another possible downside is the access pattern. If the program assesses s_blue
from multiple TUs in quick succession it could trash the cache.
However for certain programs and scenarios this could be the best option or at least "good enough". For instance (spoiler for next paragraph) in a header only library or before C++17.
Yes, but they cannot always be used.
extern
Make it an extern
declaration in the header and in just 1 TU have the definition.
// constants.hpp
extern const std::string k_blue;
// constants.cpp
#include "constants.hpp"
const std::string k_blue = "Blue";
This is clearly superior in terms of performance over OP. However you can't use it in a header only lib.
Even in a normal program static
could be preferred as the ease of declaring and defining the constants in just one place could be seen as outweighing the performance downsides in specific projects.
constexpr inline string_view
C++17A clearly better alternative if it's available (since C++17) is string_view
. It's very light weight but has all the amenities of a modern container (unlike raw const char[]
). And since you already are in C++17 you should make it constexpr inline
:
constexpr inline std::string_view k_blue = "Blue";
inline const std::string
c++17If for whatever reason you need std::string
over std::string_view
you can inline the variable for better optimization:
inline const std::string k_blue = "Blue";
Note that static
in namespace level means: "symbol is visible only for current translation unit."
Also const
at namespace level defaults to static
so this keyword is not needed.
So every time you will include this file you will have new instance of this variable. Liker will not complain that there is multiple instances of this symbol.
If you are using C++17 it would be better to use std::string_view
and constexpr
:
namespace Colors
{
constexpr std::string_view s_blue = "Blue";
}