简体   繁体   English

c ++中的静态成员函数是在多个翻译单元中复制的吗?

[英]Are static member functions in c++ copied in multiple translation units?

I have a helper class in my program which has many static functions used in different classes of my program. 我的程序中有一个辅助类,它在我的程序的不同类中使用了许多静态函数。 Eg 例如

helper.h : helper.h

Class helper {
 public: 
   static void fn1 () 
   { /* defined in header itself */ }

   /* fn2 defined in src file helper.cpp */
   static void fn2(); 
}

Helper has only static member functions. Helper只有静态成员函数。 So, no objects of helper are created by other modules. 因此,其他模块不会创建任何辅助对象。 Helper functions are used in other modules like: 辅助函数用于其他模块,如:

A.cpp

#include "helper.h"
A::foo() {
  helper::fn1(); 
  helper::fn2();
}

B.cpp

#include "helper.h"
B::foo() {
  helper::fn1();
  helper::fn2(); 
}

Does the compiler create separate copies of helper functions in A.cpp and B.cpp ? 编译器是否在A.cppB.cpp创建了辅助函数的单独副本? I read some earlier posts and I gathered from the replies that compiler will create so. 我读了一些早期的帖子,我从编译器将创建的回复中收集到了。 But when I print the address of fn1 and fn2 as printf("Address of fn1 is %p\\n", &helper::fn1); 但是当我将fn1fn2的地址打印为printf("Address of fn1 is %p\\n", &helper::fn1); and printf("Address of fn1 is %p\\n", &helper::fn1); printf("Address of fn1 is %p\\n", &helper::fn1); from both A.cpp and B.cpp , I get the same address. A.cppB.cpp ,我得到相同的地址。 I'm confused now. 我现在很困惑。 Can someone clarify, If I'm missing something. 有人可以澄清,如果我错过了什么。

The reason I'm worried about multiple copies of helper functions (if it happens) is we are trying to reduce our executable size and wanted to optimize it. 我担心辅助函数的多个副本(如果它发生)的原因是我们正在尝试减少我们的可执行文件大小并想要优化它。

Functions defined inside the class body are implicitly marked inline . 在类体内定义的函数是inline隐式标记的。 If you take the address of the function, the compiler will also create a regular copy of the function (per compilation unit), but the linker will pick just one of these copies to include in the executable, so there's only one address. 如果您获取函数的地址,编译器也将创建函数的常规副本(每个编译单元),但链接器将只选择其中一个副本以包含在可执行文件中,因此只有一个地址。

However, the inlining process could make many copies of the function, even more than the number of compilation units. 但是,内联过程可以创建函数的许多副本,甚至超过编译单元的数量。 Often the increased size of duplicating the code is offset by the increased optimization possible by eliminating argument passing and function call overhead, as well as opportunities for common subexpression elimination, etc. Although inlining is often considered a tradeoff between size and speed, the size increase is often negligible or even negative. 通常,通过消除参数传递和函数调用开销以及消除公共子表达式的机会等,可以通过增加的优化来增加重复代码的增加的大小。尽管内联通常被认为是大小和速度之间的权衡,但是大小增加通常可以忽略不计甚至是否定的。

The function that's just declared in the class and then implemented in a single compilation unit, definitely has just one copy in the executable. 刚刚在类中声明然后在单个编译单元中实现的函数,在可执行文件中肯定只有一个副本。

if visible (eg, defined in the class declaration), then it's implicitly declared inline by many compilers. 如果可见(例如,在类声明中定义),则由许多编译器隐式声明内联。

if inlined, then yes it may be copied in some cases, inlined in some cases, and partially inlined in other cases. 如果内联,那么可以在某些情况下复制,在某些情况下内联,在其他情况下部分内联。

it follows the One Definition Rule (ODR), copies found in multiple translations will be removed when linked (unless you have enabled private extern inlines, then you could really end up with redundant exported implementations). 它遵循单一定义规则(ODR),在链接时将删除多个翻译中找到的副本(除非您启用了私有外部内联,否则您最终可能会使用冗余导出的实现)。

if you are coming from C: static does not create a unique copy of the function in this case -- it just means that you may call the function without an instance of the class which declares it. 如果您来自C:静态不会在这种情况下创建函数的唯一副本 - 它只是意味着您可以在没有声明它的类的实例的情况下调用该函数。

An inlined static class method is not that different from an inlined free function. 内联静态类方法与内联自由函数没有什么不同。 Theoretically the ODR rule means that there is a single instance of the function, but in practice the compiler may have always inlined it so that there is in fact no instance of the function per se. 从理论上讲,ODR规则意味着函数有一个实例,但实际上编译器可能总是内联它,因此事实上实际上没有函数的实例。

However, the very act of taking the address of the function will force the compiler to create an instance of the function, and it is the compilation system's problem to enforce the ODR and hence ensure that you always get the same address. 但是, 获取函数地址的行为将强制编译器创建函数的实例,并且强制执行ODR是编译系统的问题,因此确保始终获得相同的地址。

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

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