是否为永远不会使用地址的静态const变量分配内存?

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

它取决于变量的类型 ,以及“常量”是否也意味着“常量表达”。 例:

static const Foo = get_foo(std::cin); static const int q = argc * 3; static const std::string s(gets()); 

这些变量是常量,但显然需要实际分配。

另一方面,以下常量表达式可能永远不会有物理存储:

 static const int N = 1000; static const std::shared_ptr vp(); // constexpr constructor! 

最重要的是,如果您小心,静态constexpr 成员变量不需要定义:

 struct Bar { int size() const { return N; } static const int N = 8; }; // does NOT need "const int Bar::N;" 

它有可能不是,但这无关紧要。 您不能仅依靠标准来依赖实施细节。

实际上,静态存储空间可以作为初始二进制加载的一部分,也可以在启动期间由运行时分配; 但总会在遇到用户代码之前发生。

除了Kerrek SB提到的约束之外,如果值本身从未在运行时使用,则可以消除const expr值的存储。

这不一定意味着不需要评估值 – 如果静态const expr仅用作分支条件,则可以静态地评估该条件,并且可以不生成其他代码路径或者可以由优化器排除。

几乎所有具有static持续时间的存储都可以被消除,如果实现可以保证行为就像存在存在一样 – 即可以在编译时评估的比较表达式 – 就像一个不同的const expr ,一个指针比较,其中已知rhs是另一个变量的别名,或者是不兼容的类型。 如果只将值读入永远不会读取的变量,也可以将其删除; 或者值可以减少到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静态存储持续时间

2.如果静态存储持续时间的对象具有初始化或具有副作用的析构函数,则即使它看起来未被使用也不应被删除,除非可以按照12.8中的规定消除类对象或其副本。

全局变量的内存由链接器保留,而不是编译器。 所以问题是链接器是否足够智能,不能为仅由值使用的全局变量保留空间。

这取决于这些数据的类型和用途; 例如,浮点常量通常必须从内存加载,因此即使您不直接使用该地址,它们也必须具有存储空间。

话虽如此,该标准确实指定是否可以优化静态存储(3.7.1.2:[basic.stc.static]):

如果具有静态存储持续时间的变量具有初始化或具有副作用的析构函数,则即使它看起来未使用也不应被消除,除非可以按照12.8中的规定消除类对象或其复制/移动。

因此,如果静态const变量具有构造函数或析构函数,则无法对其进行优化(尽管某些编译器/链接器仍会执行此操作)。 如果没有,它可以。 是否取决于链接器。