関数インライン展開の問題
更新 : 2007 年 11 月
関数のインライン展開を使用しているときには、下の点に注意してください。
インライン展開される関数はヘッダー ファイルに実装し、ほかのファイルから取り込んでください。
このヘッダー ファイルではインライン展開は有効にしてください。
// LNK2019_function_inline.cpp
// compile with: /c
// post-build command: lib LNK2019_function_inline.obj
#include <stdio.h>
struct _load_config_used {
void Test();
void Test2() { printf("in Test2\n"); }
};
void _load_config_used::Test() { printf("in Test\n"); }
次に、以下のコードを実行します。
// LNK2019_function_inline_2.cpp
// compile with: LNK2019_function_inline.lib
struct _load_config_used {
void Test();
void Test2();
};
int main() {
_load_config_used x;
x.Test();
x.Test2(); // LNK2019
}
#pragma inline_depth コンパイラ ディレクティブを使用するときは、値を 2 以上に設定します。0 ではインライン展開が無効になります。コンパイラ オプション /Ob1 または /Ob2 も使用する必要があります。
インライン展開に関して、モジュールごとに異なるコンパイル オプションを指定すると、問題が起こることがあります。C++ のライブラリをインライン展開を有効 (/Ob1 または /Ob2) にして作成し、関数本体があるヘッダー ファイルではインライン展開を無効にすると、LNK2001 エラーが発生します。ヘッダー ファイルの関数はインライン展開されていませんが、ライブラリ ファイルには存在しないために、参照の解決を試みても、アドレスがありません。
同様に、関数のインライン展開を使用しているプロジェクトで、関数をヘッダー ファイルではなく .cpp ファイルで定義していると、LNK2019 が発生します。ヘッダー ファイルは適切と思われる場所ならどこからでも取り込むことができます。ただし、この関数は .cpp ファイルがコンパイラに渡されたときにだけインライン展開されます。したがって、リンカはこの関数がほかのモジュールで使用されると、未解決の外部参照と見なします。
// LNK2019_FIP.h
struct testclass {
void PublicStatMemFunc1(void);
};
次に、以下のコードを実行します。
// LNK2019_FIP.cpp
// compile with: /c
#include "LNK2019_FIP.h"
inline void testclass::PublicStatMemFunc1(void) {}
次に、以下のコードを実行します。
// LNK2019_FIP_2.cpp
// compile with: LNK2019_FIP.cpp
// LNK2019 expected
#include "LNK2019_FIP.h"
int main() {
testclass testclsObject;
// module cannot see the implementation of PublicStatMemFunc1
testclsObject.PublicStatMemFunc1();
}