是否为从未使用地址的静态const变量分配内存?

时间:2022-09-06 14:17:38

If I never use the address of a static const variable, is memory allocated for it when using a reasonably modern compiler?

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

4 个解决方案

#1


10  

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:

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

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

#2


3  

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

有可能不是,但这并不重要。您不能依赖于实现细节,只能依赖于标准。

#3


1  

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.

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

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.

这并不一定意味着该值不需要被评估——如果静态的const expr只作为分支条件使用,那么该条件可以静态地评估,其他的代码路径可能不会生成,或者可能被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.

几乎任何类型的存储与静态时间可能会被淘汰,如果能保证实现行为好像存储在场,即比较表达式,可以评估在编译时——就像另一个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

3.7.1静态存储时间

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.

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

#4


1  

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]):

已经说过了,标准确实指定了是否可以优化静态存储(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.

如果具有静态存储持续时间的变量具有初始化或具有副作用的析构函数,即使它看上去未被使用,也不应删除它,除非类对象或其复制/移动可以按照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.

因此,如果静态const变量有构造函数或析构函数,则不能对其进行优化(尽管有些编译器/链接器无论如何都会这样做)。如果没有,它可以。这取决于链接器。

#1


10  

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:

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

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

#2


3  

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

有可能不是,但这并不重要。您不能依赖于实现细节,只能依赖于标准。

#3


1  

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.

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

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.

这并不一定意味着该值不需要被评估——如果静态的const expr只作为分支条件使用,那么该条件可以静态地评估,其他的代码路径可能不会生成,或者可能被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.

几乎任何类型的存储与静态时间可能会被淘汰,如果能保证实现行为好像存储在场,即比较表达式,可以评估在编译时——就像另一个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

3.7.1静态存储时间

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.

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

#4


1  

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]):

已经说过了,标准确实指定了是否可以优化静态存储(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.

如果具有静态存储持续时间的变量具有初始化或具有副作用的析构函数,即使它看上去未被使用,也不应删除它,除非类对象或其复制/移动可以按照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.

因此,如果静态const变量有构造函数或析构函数,则不能对其进行优化(尽管有些编译器/链接器无论如何都会这样做)。如果没有,它可以。这取决于链接器。