But if the type of a variable is »int«, the variable
also can be defined within the class specifier.
Not according to the standard. Even if an initializer is
present, the declaration in the class is not a definition.
(This is the only case in the language, I think, where an
initializer is present on something that is not a definition.)
According to the standard, it must be defined once and only once
in the program if it is used. According to the original
standard, it is used if its name appears in a potentially
evaluated expression; the latest draft changes this to exclude
cases where the object "satisfies the requirements for appearing
in a constant expression and the lvalue-to-rvalue conversion is
immediately applied."
Not providing a definition (or providing more than one) is
undefined behavior, of course, which means that the
implementation is not required to emit an error message. The
language added to the latest draft corresponds to a case where
(as far as I know) no implementation actually did emit an error
message. If you take the address of the static variable, even
indirectly (e.g. by binding it to a reference), then you will
generally have to provide a definition.
Try the following:
#include <iostream>
struct S
{
static int const i = 47 ;
} ;
void
f( int const& i )
{
std::cout << i << std::endl ;
}
int
main()
{
f( S::i ) ;
return 0 ;
}
It fails to compile (actually, fails to link) with the compilers
available to me (g++, VC++ and Sun CC).
Note too that while typically, one would declare f, above, to
take a value rather than a reference, references can appear
because of templates, e.g. std::vector<int>:
ush_back() takes a
reference to int. In such cases, it's likely that whether the
compiler complains depends on the optimization level, or more
precisely, whether it actually inlines push_back or not).