Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/152.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 删除C+中未使用(未引用)的静态全局变量常量+;_C++ - Fatal编程技术网

C++ 删除C+中未使用(未引用)的静态全局变量常量+;

C++ 删除C+中未使用(未引用)的静态全局变量常量+;,c++,C++,更新 我尝试删除静态修饰符,并尝试将它们放在一个名称空间中(以及这两个名称空间),但都不起作用。 嗨 我有一个头文件,其中包含一些常用常量,如名称和内容,这些常量会自动包含在每个项目中(下面是一个示例)。问题是,无论是否使用(引用)它们,它们都包含在已编译的二进制文件(EXE)中。如果我改用DEFINEs,那么如果不使用它们,它们自然不会被包括在内,但是const当然比DEFINEs好,所以…我试着用谷歌搜索它,但我能找到的最接近的东西就是在这里,所以没有太大的帮助。撇开i18n的问题不谈,我

更新

我尝试删除静态修饰符,并尝试将它们放在一个名称空间中(以及这两个名称空间),但都不起作用。


我有一个头文件,其中包含一些常用常量,如名称和内容,这些常量会自动包含在每个项目中(下面是一个示例)。问题是,无论是否使用(引用)它们,它们都包含在已编译的二进制文件(EXE)中。如果我改用DEFINEs,那么如果不使用它们,它们自然不会被包括在内,但是const当然比DEFINEs好,所以…我试着用谷歌搜索它,但我能找到的最接近的东西就是在这里,所以没有太大的帮助。撇开i18n的问题不谈,我怎样才能在保持易用性的同时,将未使用的保留在二进制之外呢

谢谢。


//COMMON.H:
  static const CString s_Company _T("Acme inc.");
  //etc. others
  static const CString s_Digits  _T("0123456789");

//TEST.CPP:
  #include common.h
  int main() {
    AfxMessageBox(s_Company);
  }

  //s_Company should be in the final EXE, but s_Digits should not be, but is

如果定义了明确的规则以明确何时要使用what,则可以使用如下预处理器定义:

#if defined CONFIG_COMPANY
  static const CString s_Company _T("Acme inc.");
#elif defined CONFIG_DIGITS
  static const CString s_Digits  _T("0123456789");
#endif
然后,您可以在单独的配置标头中定义或不定义这些值


顺便说一句,如果这个文件要包含在许多源文件中,那么您可能应该避免将这些常量声明为
static
。它们具有内部链接,您将在所有翻译单元中获得它们的单独副本。

如果不需要将值作为文本,您可以在头文件中将它们声明为:

extern const CString s_Company;
将它们中的每一个放在自己的源文件中,该源文件将其定义为:

const CString s_Company _T("Acme inc.");

然后你只能链接你需要的常量;链接器将在其错误消息中告诉您是否缺少任何链接!(还有一些方法可以告诉编译器不要在构建的库中公开这些符号——假设你正在构建一个库——但它们不是标准的或可移植的。)

它们没有从二进制文件中剥离的原因是因为它们被使用:
CString
不是POD类型,因此,当您在全局范围内创建它们的实例时,编译器必须生成代码来调用它们的构造函数和析构函数

如果要删除未使用的符号,只需将
CString
s替换为POD类型,如
const TCHAR*

static const TCHAR *s_Company = _T("Acme inc.");
static const TCHAR *s_Digits  = _T("0123456789");

然后,编译器将自动从二进制文件中删除未使用的常量。但是,需要记住的一点是,如果字符串在多个文件中使用,那么二进制文件中将包含这些字符串的多个副本,使用该字符串的每个翻译单元都有一个副本。甚至gcc的
-fmerge constants
选项似乎也无法解决这一问题。如果不希望发生这种情况,则需要在头文件中使用
extern
声明,然后将字符串常量的值放入源文件中(通常在一个文件中,但这不是必需的)。这还允许您更改常量,而无需重新编译使用它们的每个文件。

在Windows上,特别是使用MFC,答案是将字符串放入资源中,然后使用LoadResource/LoadString从那里加载字符串(请参阅)

在您的例子中,有两个常量cstring,因此资源编译器将生成如下内容

#define IDS_COMPANY 1
#define IDS_DIGITS  2
因此,在本例中,您将有一个带有两个字符串的.dll。您的应用程序将加载.dll(AfxLoadLibrary)。然后,当您需要字符串时,应用程序会从resource.dll加载该字符串


这就是防止Windows应用程序因全局静态字符串、位图等而膨胀的原因。

不,在实际需要之前,无法提前知道将使用什么。@Synetech what,在运行时?如果您不知道您需要这个符号,那么如何删除它呢?编译时不需要。我无法预先知道我将使用哪些常量。既然我在示例中给出的不仅仅是两个符号,那么为每个符号创建一个定义将是一个巨大的痛苦。你能把它们放在一个共享库中吗?出于好奇,你为什么要强制这些符号被剥离?@Stephan,我在示例中给出的不仅仅是两个符号,所以它们增加了二进制的大小,它们会在二进制文件中产生大量额外的内容(例如,在二进制文件中运行字符串会产生额外的无用内容)。如果您将这些对象合并到一个静态库中,然后链接到存档文件而不是对象,则链接器将只使用满足未定义引用的对象。@Donal,我在示例中给出的不仅仅是这两个文件,因此将它们分别放在一个单独的文件中将是一个可怕的混乱,特别是因为其中有些文件是相互关联的@R.S.Klatchko库是否与DLL中相同?我希望避免使用DLL,因为它们不像简单的#include那样易于使用(不必为头文件提供自己的项目,并为每一个小更改单独重新编译它)。@Synetechinc.-不是DLL,而是静态库。同意,这不像使用头文件那么简单,但也不难。由于您使用的是MS特定的代码,我猜您使用的是Visual Studio;您可以拥有项目依赖项,以便在必要时重新编译静态库。哦,对了,您是说一个LIB文件,对吗?嗯,实际上我自己并不使用这样的库(我的一些项目链接到一些第三方库)。我不清楚这会有什么帮助,因为如果链接器是一个省略未使用的东西的链接器,那么为什么它不能为项目本身这样做?@Synetech:最终,你必须不要将符号定义放在程序中。您可以通过
#ifdef
fery或不链接符号来执行此操作。如果你两种解决方案都不愿意,你就卡住了。@Adam,这是有道理的。不幸的是,我使用CString是为了组合一些,例如,
CString lcletters=“abc…”;const CString nucletters=“ABC…”;常数CString字母=字母+字母(同样,i18n除外)。使用TCHAR*将不起作用,因为编译器将其解释为添加指针。还有一些