回答編集履歴
2
インライン関数とODRの関係を追記
answer
CHANGED
@@ -16,19 +16,21 @@
|
|
16
16
|
int getM1();
|
17
17
|
int getM2();
|
18
18
|
|
19
|
-
// OK: クラス定義内でメンバ関数を定義した場合、暗黙に
|
19
|
+
// OK: クラス定義内でメンバ関数を定義した場合、暗黙にインライン関数となる
|
20
20
|
int getM3() {
|
21
21
|
return m3;
|
22
22
|
}
|
23
23
|
};
|
24
24
|
|
25
|
-
// OK: クラス定義外で明示的にinlineキーワード指定すれば
|
25
|
+
// OK: クラス定義外で明示的にinlineキーワード指定すればインライン関数となる
|
26
26
|
inline int Foo::getM1() {
|
27
27
|
return m1;
|
28
28
|
}
|
29
29
|
|
30
|
-
// NG:クラス定義外でinlineキーワードがなければ非
|
30
|
+
// NG:クラス定義外でinlineキーワードがなければ非インライン関数となる
|
31
31
|
int Foo::getM2() {
|
32
32
|
return m2;
|
33
33
|
}
|
34
|
-
```
|
34
|
+
```
|
35
|
+
|
36
|
+
ちなみに、ODR違反になるか否かは「インライン関数として**扱われるか**」という観点のみが関与します。インライン関数が**実際に**インライン展開されるかどうかは、ODRの議論とは無関係です。`inline`キーワードはコンパイラへの**最適化ヒント情報**という側面ももり、こちらは単にコンパイラによる最適化性能の話です。最近のまともなコンパイラであれば、非インライン関数であってもインライン展開を行ったり、インライン関数であっても通常の関数呼び出しになったりします。
|
1
inline関数となるパターンを例示
answer
CHANGED
@@ -4,4 +4,31 @@
|
|
4
4
|
|
5
5
|
ヘッダファイルに「定義」が書いてある場合、そのヘッダファイルをincludeするすべてのコンパイル単位(cppファイル)に同一の「定義」が複製されて登場します。これらのコンパイルされたファイルをリンクして1つのプログラムを生成するとき、そのプログラムには同一の「定義」が複数含まれることになります。これは先のODR違反となるため、正しく動作する保証のないプログラムが出来上がります。
|
6
6
|
|
7
|
-
このルールの例外として、テンプレート(`template`)定義や、インライン関数(`inline`)定義はヘッダファイルに書いてもOKです。
|
7
|
+
このルールの例外として、テンプレート(`template`)定義や、インライン関数(`inline`)定義はヘッダファイルに書いてもOKです。何がインライン関数となるかについては、少々ややこしいルールがあるので下記も参考にしてください。
|
8
|
+
|
9
|
+
```lang-cpp:
|
10
|
+
// (複数cppファイルからincludeされるヘッダファイルと仮定)
|
11
|
+
|
12
|
+
class Foo {
|
13
|
+
int m1, m2, m3;
|
14
|
+
public:
|
15
|
+
// ここではメンバ関数の宣言のみ
|
16
|
+
int getM1();
|
17
|
+
int getM2();
|
18
|
+
|
19
|
+
// OK: クラス定義内でメンバ関数を定義した場合、暗黙にinline関数となる
|
20
|
+
int getM3() {
|
21
|
+
return m3;
|
22
|
+
}
|
23
|
+
};
|
24
|
+
|
25
|
+
// OK: クラス定義外で明示的にinlineキーワード指定すればinline関数となる
|
26
|
+
inline int Foo::getM1() {
|
27
|
+
return m1;
|
28
|
+
}
|
29
|
+
|
30
|
+
// NG:クラス定義外でinlineキーワードがなければ非inline関数となる
|
31
|
+
int Foo::getM2() {
|
32
|
+
return m2;
|
33
|
+
}
|
34
|
+
```
|