简体   繁体   English

包含在许多转换单元中的静态常量的开销?

[英]Overhead of static constants when included into many translation units?

In a header file, global constants can be declared and (pre)defined in a single line. 在头文件中,可以在一行中声明和(预)定义全局常量。

// constants.h
namespace Constant{
    static const unsigned int framerate = 60;
    static const char * const windowName = "Test";
    static const unsigned char * const cursorBitmap = { lots of data };
}

I like this format because it lets me keep my constants in one place, and avoids needing to declare the constant in one file and define it in another, helping with readability. 我喜欢这种格式,因为它使我可以将常量保存在一个位置,并且避免在一个文件中声明常量并在另一个文件中定义常量,从而提高了可读性。 When any translation unit includes constants.h however, it expands these definitions in place, per unit . 但是,当任何转换单位都包含constants.h时,它将按单位在适当位置扩展这些定义。

My question is, will this cause significant overhead if I include constants.h into many translation units and, for instance, cursorBitmap and other array constants are significantly large? 我的问题是,如果我将constants.h包含在许多转换单元中,例如cursorBitmap和其他数组常量很大,这是否会导致大量开销? Will my program contain 100 copies of each string and array literal if I include it into 100 units? 如果我将其包含在100个单位中,我的程序是否将每个字符串和数组文字包含100个副本? Or will only the pointers and values be copied? 还是只复制指针和值?

If there is overhead, is there a way I can avoid it without needing to separate declaration and definition? 如果有开销,是否有一种方法可以避免它而无需分开声明和定义?

(also I'm guessing the 'static' is redundant in this usage, but I like to put it there anyway) (我也猜想在这种用法中“静态”是多余的,但无论如何我都喜欢把它放在那里)

Whether string literals are duplicated in the various translation units is a Quality of Implementation issue. 字符串文字是否在各种翻译单元中重复是实现质量的问题。

The directly declared objects will be duplicated in each translation unit where this header is included. 直接声明的对象将在包含此标头的每个翻译单元中重复。 It's not much though. 虽然不多。 And in a translation unit where some constant's address isn't directly or indirectly used, it may be optimized away. 在不直接或间接使用某些常量地址的转换单元中,可以对其进行优化。

If you want to ensure only one copy of each constant, or even no copy, then you can use a class template, like this: 如果要确保每个常量只有一个副本,甚至没有副本,则可以使用类模板,如下所示:

constants.h 常数h
 #pragma once template< class Dummy > struct Constant_{ static const unsigned int framerate; static const char * const windowName; static const unsigned char * const cursorBitmap; }; template< class Dummy > const unsigned int Constant_<Dummy>::framerate = 60; template< class Dummy > const char * const Constant_<Dummy::windowName = "Test"; template< class Dummy > const unsigned char * const Constant_<Dummy>::cursorBitmap = ...; using Constant = Constant_<void>; 

But it's IMHO more work than it's worth. 但是,恕我直言,这比价值还高。

A similar alternative is to use inline functions, one for each constant. 一种类似的替代方法是使用inline函数,每个常数一个。

Will my program contain 100 copies of each string and array literal if I include it into 100 units? 如果我将其包含在100个单位中,我的程序是否将每个字符串和数组文字包含100个副本? Or will only the pointers and values be copied? 还是只复制指针和值?

The standard does not promise consolidation of string literals, so it's up to the implementation. 该标准不承诺合并字符串文字,因此取决于实现。 A simple test using GCC 5.1.1 on GNU/Linux showed that the string literals are not consolidated in an unoptimized build, but are consolidated when -O or -Os is used. 在GNU / Linux上使用GCC 5.1.1进行的简单测试表明,字符串文字不是在未优化的构建中合并的,而是在使用-O-Os时合并的。 But that is just merging the actual char arrays. 但这只是合并实际的char数组。 To the extent that the compiler doesn't optimize away the storage for the pointer, or for the numerical constants (if they are local to the translation unit, not ODR-used, and of POD type, they are obvious candidates for elimination under the as-if rule), however, the compiler may not be able to consolidate them easily. 在某种程度上,编译器没有优化指针或数字常量的存储(如果它们是转换单元的本地存储,不是ODR使用的,并且是POD类型的,则它们显然是在以下情况下消除的候选对象)但是,编译器可能无法轻松合并它们。 The standard requires them to be different objects and hence must have different addresses. 该标准要求它们是不同的对象,因此必须具有不同的地址。 The as-if rule may still allow their removal, even if you were to take their addresses, but this would generally require global program optimization aka link-time optimization, including libraries, that the implementation may not support, support only in a limited fashion, and/or only depending on compiler and linker settings. 即使您要获取其地址,按原样的规则仍可能允许将其删除,但这通常需要实现可能不支持的全局程序优化或链接时优化(包括库),实现可能不支持,仅以有限的方式支持和/或仅取决于编译器和链接器设置。 In other words, it just might happen under the right circumstances, but it is much more likely not to happen. 换句话说,它只会在适当的情况下发生,但更有可能不会发生。

My own test indicates that GCC 5.1.1 does not consolidate static const unsigned int objects exposed by const ref, even with -Os -flto (optimize for size and enable link-time optimization). 我自己的测试表明,即使使用-Os -flto (针对大小进行优化并启用链接时优化),GCC 5.1.1也不合并由const ref公开的static const unsigned int对象。 I would frankly be surprised if any contemporary implementation did perform this difficult and obscure optimization. 坦率地说,如果任何当代的实现都执行了这一困难而晦涩的优化,我将感到惊讶。

(also I'm guessing the 'static' is redundant in this usage, but I like to put it there anyway) (我也猜想在这种用法中“静态”是多余的,但无论如何我都喜欢把它放在那里)

It's not redundant if you have multiple translation units because you would otherwise run afoul of the one definition rule (ODR). 如果有多个翻译单元,这不是多余的,因为否则会违反一个定义规则(ODR)。 As a side note, however, static at namespace scope has been considered syntactically obsolete for a long time (consider using anonymous namespaces, introduced in C++98, instead). 但是,作为旁注,很长时间以来,在命名空间范围内, static语法已被认为过时了(考虑使用在C ++ 98中引入的匿名命名空间)。

(in response to Cheers and hth. - Alf) (响应干杯和hth。-Alf)

If you want to ensure only one copy of each constant, or even no copy, then you can use a class template, like this: 如果要确保每个常量只有一个副本,甚至没有副本,则可以使用类模板,如下所示:

No such luck. 没有这种运气。 There's no guarantee in the standard about how much space is used for the templates. 标准中不能保证模板使用了多少空间。 All the template does guarantee is that only one of the potentially many copies is used – or appears to be used, under the as-if rule. 模板所做的全部保证是,按照潜在规则,仅使用了或似乎要使用的潜在多个副本中的一个。 In fact, it's worse than that because at least GCC 5.1.1 in fact does not remove a redundant static const unsigned int even with -Os -flto on my system. 实际上,这比那更糟,因为至少GCC 5.1.1实际上即使在系统上使用-Os -flto不会删除冗余的static const unsigned int This means with two translation units, the initializer value for the unsigned int can be found in two separate locations, even though only one of them is used (all pointers and references refer to this location only). 这意味着使用两个转换单元,即使在仅使用其中一个的情况下,也可以在两个单独的位置找到unsigned int的初始化程序值(所有指针和引用仅引用此位置)。

First, using static in namespace is deprecated since C++98: 首先,自C ++ 98起,不建议在名称空间中使用static

D.2 static keyword D.2 static关键字
The use of the static keyword is deprecated when declaring objects in namespace scope (see 3.3.5) 在命名空间范围内声明对象时,不建议使用static关键字(请参阅3.3.5)

Second, const implies internal linkage in C++ by itself. 其次, const暗示C ++本身具有内部链接。

Third, exact answer depends on compiler and options you use. 第三,确切答案取决于您使用的编译器和选项。 Duplicates can be eliminated by compiler/linker, especially if LTO (Link Time Optimization) can be used. 可以通过编译器/链接器消除重复,特别是如果可以使用LTO(链接时间优化)。

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

相关问题 在确保翻译单元之间的可用性时是否静态弃用? - Is static deprecated when ensuring availability between translation units? 静态,全局和多个翻译单元 - Static, global and multiple translation units 一个模块中有多少个翻译单元? - How many translation units in one module? 将C ++代码拆分成多个转换单元会导致可执行文件大小的开销吗? - Does splitting C++ code into multiple translation units introduce overhead on the executable size? 在不同翻译单元中模板类静态变量的显式实例化 - explicit instantiation of static variable of a template class in different translation units c ++中的静态成员函数是在多个翻译单元中复制的吗? - Are static member functions in c++ copied in multiple translation units? 多次#included 保护的 header 文件将如何在不同的翻译单元内? - How a multiple times #included guarded header file will be inside different translation units? 隐式 class 实例化翻译单元:链接时的多重定义 - Implicit class instantiations translation units: multiple definition when linking 独立的翻译单位 - Separate translation units c ++在不同翻译单元中交互的非本地静态对象的示例 - c++ example of non-local static objects interacting in different translation units
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM