Scott Meyers writes in Effective Modern C++, Item 30 page 210, that there's
no need to define integral
static const
data members in classes; declarations alone suffice,
then the sample code is
class Widget { public: static const std::size_t MinVals = 28; // MinVals' declaration; ... }; ... // no defn. for MinVals std::vector<int> widgetData; widgetData.reserve(Widget::MinVals); // use of MinVals
I was convinced that static const std::size_t MinVals = 28;
is declaration and also a definition, as it is giving a value to MinVals
, but the comment seems to claim that's only a declaration; the second comment actually claims there's no definition. The text after the code, indeed reads
MinVals
lacks a definition.
Which confirms that static const std::size_t MinVals = 28;
is not a definition, so I'm a bit confused.
cppreference doesn't help me much (my bold-italic):
If a
static
data member of integral or enumeration type is declaredconst
(and notvolatile
), it can be initialized with an initializer in which every expression is a constant expression, right inside the class definition:struct X { const static int n = 1; const static int m{2}; // since C++11 const static int k; }; const int X::k = 3;
but first two lines in the class look definitions to me.
The same goes for a following example on cppreference:
struct X { static const int n = 1; static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; // X::n and X::m are odr-used const int X::n; // … so a definition is necessary constexpr int X::m; // … (except for X::m in C++17)
where I'd have said static const int n = 1;
is a definition, but it is not, based on the second to last comment.
The const variable is basically used for declaring a constant value that cannot be modified. A static keyword is been used to declare a variable or a method as static. A const keyword is been used to assign a constant or a fixed value to a variable.
“static const” is basically a combination of static(a storage specifier) and const(a type qualifier). The static determines the lifetime and visibility/accessibility of the variable.
They mean exactly the same thing. You're free to choose whichever you think is easier to read. In C, you should place static at the start, but it's not yet required.
static means the value is shared between all instances of the class and const means it doesn't change.
no need to define integral static const data members in classes; declarations alone suffice,
Declarations alone suffice only if that object is not ODR-used, that is, if a data member is not used in a context that would require its address to exist (like binding to a reference or applying operator &
). The presence of an initializer does not equal a definition.
In the example from the book, it's clear that MinVals
is not ODR-used, i.e., the compiler can use its value directly, without having to create an object in memory, and so the statement:
widgetData.reserve(Widget::MinVals);
becomes:
widgetData.reserve(28);
If, however, in any other place, MinVals
were ODR-used, that would make the program ill-formed.
All other examples from cppreference clearly indicate when a value is ODR-used and a definition is required, and when not:
struct X { const static int n = 1; const static int m{2}; // since C++11 const static int k; }; const int X::k = 3;
n
and m
are declarations with initializers. An attempt to obtain the address of either n
or m
should fail.
struct X { static const int n = 1; static constexpr int m = 4; }; const int *p = &X::n, *q = &X::m; const int X::n; constexpr int X::m;
Expressions &X::n
and &X::m
count as ODR-use of n
and m
, respectively (that is, an address is requested). For a constexpr
static data members, a definition was required prior to C++17. From C++17, static constexpr
data members are implicitly inline
, which means, no out-of-class definition is needed, as they are definitions themselves.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With