不思議な現象に出くわしたので、エントリにしてみるテスト。
C++でプログラミングしていて、ヘッダにクラスのコンストラクタの定義を含めず、宣言だけを書くというのはよくあることだと思います。 次のようなヘッダファイルを考えてみます。
sym.h:
#ifndef _SYM_H_ #define _SYM_H_ class Sym { public: Sym(); }; // Sym #endif // _SYM_H_
実装は sym.cc に書きます。
#include "sym.h" Sym::Sym() { } int main() { Sym sym; return 0; }
これらをg++でコンパイルして、生成されるオブジェクトファイルを覗いてみると、驚きました。
% nm sym | c++filt
0000200c D _NXArgc
00002008 D _NXArgv
00001fde T Sym::Sym()
00001fd6 T Sym::Sym()
00002000 D ___progname
00001fc8 t __dyld_func_lookup
00001000 A __mh_execute_header
00002004 D _environ
U _exit
00001fe6 T _main
00002010 d dyld__mach_header
00001fb4 t dyld_stub_binding_helper
00001f74 T start
なんで Sym::Sym()が2つ存在するんだ?
そして、ヘッダファイルに定義も含めると、1つになります。
#ifndef _SYM_H_ #define _SYM_H_ class Sym { public: Sym() {} }; // Sym #endif // _SYM_H_
nm sym | c++filt
0000200c D _NXArgc
00002008 D _NXArgv
00001fb6 T Sym::Sym()
U ___gxx_personality_v0
00002000 D ___progname
00001f90 t __dyld_func_lookup
00001000 A __mh_execute_header
00002004 D _environ
U _exit
00001f9e T _main
00002010 d dyld__mach_header
00001f7c t dyld_stub_binding_helper
00001f3c T start
なぜだー。Mac OS X / Linux で確認しています。
使えるメモリが極めて限られている状況だと、こういう小さなところでも無駄は減らしたい。でもヘッダファイルに実装を書きまくるのは、できれば避けたいものです。
原因が分かるかたいらっしゃれば、ご教授ください ><
再現するためのコード一式を、symbols.zip に固めました。
Makefile中の CXXFLAGS += -DCOMPILE_BY_SPLIT のところを無効にするとヘッダファイルでコンストラクタの定義を行い、有効にすると.ccの中で定義する、というふうにしています。
日本語