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

时间:2011-11-28 00:01:36

标签: c++ c optimization static const

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

4 个答案:

答案 0 :(得分:10)

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

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<void> vp();  // constexpr constructor!

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

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

答案 1 :(得分:3)

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

答案 2 :(得分:1)

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

除了 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 :(得分:1)

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

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

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

  

如果具有静态存储持续时间的变量具有初始化或a   具有副作用的破坏者,即使它也不会被消除   似乎未使用,除了类对象或其复制/移动可能   按照12.8的规定予以淘汰。

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