简体   繁体   中英

Is memory allocated for a static const variable whose address is never used?

如果我从不使用静态const变量的地址,那么在使用合理的现代编译器时是否为它分配了内存?

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;"

There is chance that it isn't, but that doesn't matter. You can't rely on implementation details, only on the standard.

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 - ie 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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM