简体   繁体   English

没有在类中使用const静态变量进行优化吗?

[英]not used const static variable in class optimized out?

Can a reasonable decent compiler discard this const static variable 一个合理的体面的编译器可以丢弃此const静态变量吗?

class A{
     const static int a = 3;
}

if it is nowhere used in the compiled binary or does it show up anyway in the binary? 如果在编译的二进制文件中没有使用它,还是在二进制文件中仍然显示了它?

Short answer: Maybe. 简短的回答:也许吧。 The standard does not say the compiler HAS to keep the constants (or strings, or functions, or anything else), if it's never used. 如果从未使用过,该标准并未说明编译器必须保留常量(或字符串,函数,或其他任何东西)。

Long answer: It very much depends on the circumstances. 长答案:这在很大程度上取决于具体情况。 If the compiler can clearly determine that it is not used, it will remove unused constants. 如果编译器可以清楚地确定未使用它,它将删除未使用的常量。 If it can't make that determination, it can not remove the unused constant, since the constant COULD be used by something that isn't currently known by the compiler (eg another source file). 如果无法确定,则无法删除未使用的常量,因为该常量可能被编译器当前未知的某些内容(例如,另一个源文件)使用。

For example, if class A is inside a function, the compiler can know this class is not used elsewhere, and if the constant isn't used in the function, then it's not used anywhere. 例如,如果class A在函数内部,则编译器可以知道该类未在其他地方使用,如果常量未在函数中使用,则它在任何地方都不会使用。 If the class is in a "global" space, such that it could be used somewhere else, then it will need to keep the constant. 如果该类位于“全局”空间中,以便可以在其他地方使用它,则它将需要保持常量。

This gets even more interesting with "whole program optimization" or "link time optimization" (both from now on called LTO), where all the code is actually optimized as one large lump, and of course, "used" or "not used" can be determined for all possible uses. 这对于“整个程序优化”或“链接时间优化”(从现在开始都称为LTO)变得更加有趣,其中所有代码实际上都被优化为一个大块,当然,“使用”或“未使用”可以确定所有可能的用途。

As you can imagine, the result will also depend on how clever the compiler (and linker for the LTO) is. 可以想象,结果还取决于编译器(和LTO的链接器)的智能程度。 All compilers should follow the principle of "if in doubt keep it". 所有编译器都应遵循“如有疑问请保留”的原则。

You can of course experiment, and write some code where you use the variable, and then remove the use, and see what difference it makes to the assembly code (eg g++ -S x.cpp or clang++ -S x.cpp , and look at the resulting xs file). 当然,您可以进行实验,并在使用该变量的位置编写一些代码,然后删除该使用,然后查看它与汇编代码有什么区别(例如g++ -S x.cppclang++ -S x.cpp ,然后看一下在生成的xs文件中)。

When optimizations are disabled, the answer is compiler-dependent. 禁用优化后,答案取决于编译器。 But when optimizations are enabled, the end result is the same irrespective of the compiler. 但是,启用优化后,无论编译器如何,最终结果都是相同的。 Let's assume that optimizations are enabled. 假设启用了优化。

The compiler will not emit a definition for a const static field in the generated object file when both of the following conditions holds: 当同时满足以下两个条件时,编译器将不会为生成的目标文件中的const static字段发出定义:

  1. It can resolve all uses of the field with the constant value it was initialized to. 它可以使用初始化为该常量的值来解析该字段的所有使用。
  2. There is at most one source code file that has used the field (there is an exception which I'll discuss at the end). 最多有一个使用该字段的源代码文件(有一个例外情况,我将在最后讨论)。

I'll discuss the second condition later. 稍后我将讨论第二种情况。 But now let's focus on the first. 但是现在让我们专注于第一个。 Let's see an example. 让我们来看一个例子。 Suppose that the target platform is 32-bit and that we have defined the following type: 假设目标平台是32位的,并且我们定义了以下类型:

// In MyClassA.h
class MyClassA{
public:
     const static int MyClassAField;
};

// In MyClassA.cpp (or in MyClassA.h if it was included in at most one cpp file)
const int MyClassA::MyClassAField = 2;

Most compilers consider int to be a 32-bit signed integer. 大多数编译器都将int视为32位有符号整数。 Therefore, on a 32-bit processor, most instructions can handle a 32-bit constant. 因此,在32位处理器上,大多数指令可以处理32位常量。 In this case, the compiler will be able to replace any uses of MyClassAField with the constant 2 and that field will not exist in the object file. 在这种情况下,编译器将能够使用常量2替换MyClassAField任何使用,并且该字段在目标文件中将不存在。

On the other hand, if the field was of type double , on a 32-bit platform, instructions cannot handle 64-bit values. 另一方面,如果该字段的类型为double ,则在32位平台上,指令将无法处理64位值。 In this case, most compilers emit the field in the object file and uses SSE instructions and registers to 64-bit value from memory and process them. 在这种情况下,大多数编译器会在目标文件中发出该字段,并使用SSE指令并从内存中将其注册为64位值并对其进行处理。

Now I'll explain the second condition. 现在,我将解释第二个条件。 If there is more than one source code file that is using the field, it cannot be eliminated (irrespective of whether Whole Program Optimization (WPO) is enabled or not) because some object file has to include the definition of the field so that the linker can use it for other object files. 如果有多个使用该字段的源代码文件,则无法消除该文件(无论是否启用了整个程序优化(WPO) ),因为某些对象文件必须包含该字段的定义,以便链接程序可以将其用于其他目标文件。 However, the linker, if you specified the right switch, can eliminate the field from the generated binary. 但是,链接器(如果指定了正确的开关)可以从生成的二进制文件中消除该字段。

This is a linker optimization enabled with /OPT:REF for VC++ and --gc-sections for gcc. 对于VC ++,这是通过/ OPT:REF启用的链接器优化,对于gcc是--gc-sections For icc, the names of the switches are the same (/OPT:REF on Windows and --gc-sections on Linx and OSX). 对于icc,开关的名称相同(Windows上为/ OPT:REF,Linx和OSX为--gc-sections)。 However, the compiler has to emit every function and static or global field in a separate section in the object file so that the linker can eliminate it. 但是,编译器必须在目标文件的单独部分中发出每个函数以及静态或全局字段,以便链接程序可以消除它。

There is a catch, however. 但是有一个陷阱。 If the field has been defined inline as follows: 如果已按如下内联定义字段:

class MyClassA{
public:
     const static int MyClassAField = 2;
};

Then the compiler itself will eliminate the definition of this field from every object file that uses it. 然后,编译器本身将从使用该字段的每个目标文件中删除该字段的定义。 That's because every source code file that uses it includes a separate definition. 这是因为使用它的每个源代码文件都包含一个单独的定义。 Each of them is compiled separately, the compiler itself will optimize the field away using an optimization called constant propagation. 它们每个都是单独编译的,编译器本身将使用称为常量传播的优化来优化该字段。 In fact, the VC++ compiler perform this optimization even if optimizations are disabled. 实际上,即使禁用优化,VC ++编译器也会执行此优化。

When optimizations are disabled, whether a const static field will be eliminated or not depends on the compiler, but probably it will not be eliminated. 禁用优化后,是否消除const static字段取决于编译器,但可能不会消除。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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