繁体   English   中英

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

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

我的程序中有一个辅助类,它在我的程序的不同类中使用了许多静态函数。 例如

helper.h

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

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

Helper只有静态成员函数。 因此,其他模块不会创建任何辅助对象。 辅助函数用于其他模块,如:

A.cpp

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

B.cpp

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

编译器是否在A.cppB.cpp创建了辅助函数的单独副本? 我读了一些早期的帖子,我从编译器将创建的回复中收集到了。 但是当我将fn1fn2的地址打印为printf("Address of fn1 is %p\\n", &helper::fn1); printf("Address of fn1 is %p\\n", &helper::fn1); A.cppB.cpp ,我得到相同的地址。 我现在很困惑。 有人可以澄清,如果我错过了什么。

我担心辅助函数的多个副本(如果它发生)的原因是我们正在尝试减少我们的可执行文件大小并想要优化它。

在类体内定义的函数是inline隐式标记的。 如果您获取函数的地址,编译器也将创建函数的常规副本(每个编译单元),但链接器将只选择其中一个副本以包含在可执行文件中,因此只有一个地址。

但是,内联过程可以创建函数的许多副本,甚至超过编译单元的数量。 通常,通过消除参数传递和函数调用开销以及消除公共子表达式的机会等,可以通过增加的优化来增加重复代码的增加的大小。尽管内联通常被认为是大小和速度之间的权衡,但是大小增加通常可以忽略不计甚至是否定的。

刚刚在类中声明然后在单个编译单元中实现的函数,在可执行文件中肯定只有一个副本。

如果可见(例如,在类声明中定义),则由许多编译器隐式声明内联。

如果内联,那么可以在某些情况下复制,在某些情况下内联,在其他情况下部分内联。

它遵循单一定义规则(ODR),在链接时将删除多个翻译中找到的副本(除非您启用了私有外部内联,否则您最终可能会使用冗余导出的实现)。

如果您来自C:静态不会在这种情况下创建函数的唯一副本 - 它只是意味着您可以在没有声明它的类的实例的情况下调用该函数。

内联静态类方法与内联自由函数没有什么不同。 从理论上讲,ODR规则意味着函数有一个实例,但实际上编译器可能总是内联它,因此事实上实际上没有函数的实例。

但是, 获取函数地址的行为将强制编译器创建函数的实例,并且强制执行ODR是编译系统的问题,因此确保始终获得相同的地址。

暂无
暂无

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

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