質問するログイン新規登録

回答編集履歴

2

インライン関数とODRの関係を追記

2015/06/09 12:57

投稿

yohhoy
yohhoy

スコア6191

answer CHANGED
@@ -16,19 +16,21 @@
16
16
  int getM1();
17
17
  int getM2();
18
18
 
19
- // OK: クラス定義内でメンバ関数を定義した場合、暗黙にinline関数となる
19
+ // OK: クラス定義内でメンバ関数を定義した場合、暗黙にインライン関数となる
20
20
  int getM3() {
21
21
  return m3;
22
22
  }
23
23
  };
24
24
 
25
- // OK: クラス定義外で明示的にinlineキーワード指定すればinline関数となる
25
+ // OK: クラス定義外で明示的にinlineキーワード指定すればインライン関数となる
26
26
  inline int Foo::getM1() {
27
27
  return m1;
28
28
  }
29
29
 
30
- // NG:クラス定義外でinlineキーワードがなければ非inline関数となる
30
+ // NG:クラス定義外でinlineキーワードがなければ非インライン関数となる
31
31
  int Foo::getM2() {
32
32
  return m2;
33
33
  }
34
- ```
34
+ ```
35
+
36
+ ちなみに、ODR違反になるか否かは「インライン関数として**扱われるか**」という観点のみが関与します。インライン関数が**実際に**インライン展開されるかどうかは、ODRの議論とは無関係です。`inline`キーワードはコンパイラへの**最適化ヒント情報**という側面ももり、こちらは単にコンパイラによる最適化性能の話です。最近のまともなコンパイラであれば、非インライン関数であってもインライン展開を行ったり、インライン関数であっても通常の関数呼び出しになったりします。

1

inline関数となるパターンを例示

2015/06/09 12:57

投稿

yohhoy
yohhoy

スコア6191

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
+ ```