If I never use the address of a static const variable, is memory allocated for it when using a reasonably modern compiler?
问题:
回答1:
It depends on the type of the variable, and on whether "constant" also means "constant expression". Example:
static const Foo = get_foo(std::cin);
static const int q = argc * 3;
static const std::string s(gets());
These variables are const, but blatantly need an actual allocation.
On the other hand, the following constant expression may never have physical storage:
static const int N = 1000;
static const std::shared_ptr<void> vp(); // constexpr constructor!
Most importantly, static constexpr member variables don't need a definition if you're careful:
struct Bar
{
int size() const { return N; }
static const int N = 8;
};
// does NOT need "const int Bar::N;"
回答2:
There is chance that it isn't, but that doesn't matter. You can't rely on implementation details, only on the standard.
回答3:
In practice, space for static storage can be allocated as part of the initial binary loading, or by the runtime during startup; but will always happen before user code is encountered.
In addition to the constraints that Kerrek SB mentions, the storage for a const expr
value could be eliminated if the value itself is never used at runtime.
This wouldn't necessarily mean that the value needs to not be evaluated - if a static const expr
were only used as a branch condition, that condition may be evaluated statically and other code paths may not be generated or may be excluded by the optimiser.
Pretty much any storage with static
duration may be eliminated if the implementation can guarantee behaviour as though the storage were present - i.e. a comparison expression that can be evaluated at compile time - like a different const expr
, a pointer comparison where the rhs is known to be an alias to a different variable, or perhaps an incompatible type. It may also be eliminated if the value is only read into variables that are never read themselves; or where the value may be reduced to a const expr
.
struct Foo{};
static Foo bar; // static instance
Foo* func() {
if ( ! (&bar) ) { // always non-NULL
// this block may be eliminated
Foo* myCopy(new Foo(bar));
return myCopy;
}
// so 'bar' is never referred to, and we know it has no side-
// effects, so the static variable can be eliminated
return new Foo();
}
3.7.1 Static storage duration
2.
If an object of static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy may be eliminated as specified in 12.8.
回答4:
Memory for global variables is reserved by the linker, not the compiler. So the question is whether the linker is smart enough to not reserve space for global variables that are only used by value.
It depends on the type and use of such data; for example, floating point constants generally must be loaded from memory, so they must have storage even if you don't directly use the address.
Having said that, the standard does specify whether you can optimize out static storage (3.7.1.2: [basic.stc.static]):
If a variable with static storage duration has initialization or a destructor with side effects, it shall not be eliminated even if it appears to be unused, except that a class object or its copy/move may be eliminated as specified in 12.8.
So if the static const variable has a constructor or destructor, it cannot be optimized out (although some compilers/linkers will do this anyway). If it doesn't, it can. Whether it will depends on the linker.