インライン関数のコンパイルについて

[戻る]
とよ [E-Mail] 2009/05/22(金) 11:20:44
VCというより、C++についての質問です。
 

 インライン関数について勉強した結果、

・コンパイル時に呼び出される位置に埋め込まれるように展開されるため、オーバーヘ
 ッド時間がかからない

ということは理解できました。

 例えば、定義したインライン関数が、1度もメインプログラム上で使われない場合は、
その関数はコンパイルさえされないのでしょうか?プログラムファイル実行時には、跡
形もなく消えているのでしょうか?よろしくお願いします。

 ちなみに、通常の関数は、1度も呼び出しがなくても、コンパイルされ、プログラムに
組み込まれていると解釈しています。(実行時、メモリ上に存在するが、全く呼ばれない
状態)

επιστημη [E-Mail] [HomePage] 2009/05/22(金) 11:30:29
> プログラムファイル実行時には、跡形もなく消えているのでしょうか?

マクロと同じと思っていいでしょう。
使われなければ展開されません。

> ちなみに、通常の関数は、1度も呼び出しがなくても、コンパイルされ、プログラムに
組み込まれていると解釈しています。

そうとも限らない。
呼ばれないならリンクすらされていないことだってあります。
そうであれば、実行モジュール中に存在しません。

aetos 2009/05/22(金) 12:05:14
> 使われなければ展開されません。

展開されず消える可能性もあるが、処理系の裁量次第、が正しいのでは?

とよ [E-Mail] 2009/05/22(金) 12:08:08
 返答ありがとうございます。

 マクロと同じとなると、ファイル内でのインライン関数のプロトタイプ宣言のしかた
などは、変な感じがします。(そういうルールだと言われるとそれまでですが・・・)

> 呼ばれないならリンクすらされていないことだってあります。
> そうであれば、実行モジュール中に存在しません。

 ということは、

 1. ソースコードがコンパイルされて機械語(オブジェクトコード?)になる。
 2. リンク段階で必要な関数のアドレスなどをメインプログラムに組み込んでいく。
 3. 使わない関数のオブジェクトコードは消去

という流れで、実行ファイルが出来上がるのでしょうか?

 「ファイルごとにコンパイル」→「リンク」の順なので、使わない関数もコンパイル
はされるんですよね?
 
 作成したソースファイルは全てリンクされているようなイメージだったのですが、
リンクは、もっと小さな単位で行われているということでしょうか?(関数単位とか)

tetrapod 2009/05/22(金) 12:08:49
インライン関数指定は、人間がコンパイラに対して
「インライン化することを推奨する」のであって
「インライン化しなければならないことを指定する」のではないため
常にいかなる場合にもインライン展開されるわけではない、という点に注意。

あるファイルではインライン指定した関数が実際にインライン展開された
あるファイルではインライン指定した関数がインライン展開されなかった
という状況は[言語規格書的に]あってよい。

なので、質問の答えとしては
[言語規格書的答え]
コンパイラやコンパイルオプションによって異なり一概にいえない。
となる。

まったく跡形もなく消滅する
インライン展開されないで通常の関数としてコンパイルされたものが未使用で残る
一部インライン展開され一部通常の関数として混在する
どれでもありえる。

tetrapod 2009/05/22(金) 12:13:07
> リンクは、もっと小さな単位で行われているということでしょうか?(関数単位とか)
最近の賢いリンカーならば Yes

・未使用な関数や変数は自動的に除去されるような処理を行う
・非インライン展開された同一内容の関数が複数個あれば1つにまとめてしまう
 (関数テンプレートを展開するとごく普通にそういう事態になる)
などの処理が行われていることが多い。

とよ [E-Mail] 2009/05/22(金) 13:05:15
[[解決]]
 回答くださった皆さん、ありがとうございます。
 

・インライン関数はマクロと同じで、プリプロセッサ段階で処理されるので、使われな
 ければ展開されないことがある。(処理系依存)
・コンパイラがインライン展開が必要ないと<判断したときは、通常の関数のようにコン
 パイルされ、実行ファイル上で未使用であれば、実体が残るか否かは処理系依存。

と頭の中で整理できました。
 
 それにしてもコンパイラを作った人はすごいですね。

 今までは、使う関数だけを引用して新規ファイルを作って実装していたんですが、い
ろんなファイルを全部プロジェクトに詰め込んでしまっても、結果的には同じ実行ファ
イルが吐き出されてたんですね〜。(無駄なものを省いてやっていたつもりが・・・)

aetos 2009/05/22(金) 13:09:46
> ・インライン関数はマクロと同じで、プリプロセッサ段階で処理される

使われない場合はバッサリ消えることがあるという点ではマクロと同じだが、プリプロ
セッサ段階で処理されるということまで同じではない。

> ・コンパイラがインライン展開が必要ないと判断したときは

というより、インライン展開しない方がよいと判断した時は、かと。

> 結果的には同じ実行ファイルが吐き出されてたんですね

繰り返し言うように、処理系依存なので、必ず最小限の内容になるとは限らない。
冒頭でも

> VCというより、C++についての質問です。

と言われているように、VC++ のこのバージョンでこのコンパイルオプションでこのソー
スコードを…まで特定できれば生成されるバイナリを特定できるだろうが、C++ 一般に
ついて言うならば、考え得る最大限に無駄なコードを生成するコンパイラが無いとも言
い切れない。

aetos 2009/05/22(金) 13:14:10
インライン指定した関数がインライン化されない場合もあれば、インライン指定してい
ない関数がインライン化される場合もある。
http://msdn.microsoft.com/ja-jp/library/47238hez.aspx

要するに、「うまくいけばラッキー」程度に思っておくのがよいかと。

ITO 2009/05/22(金) 16:53:17
> VCというより、C++についての質問です。
コンパイラーによって変わってしまいますよね。
C++の規格に一番近い処理を行うコンパイラーってやっぱGCCですかね?
 やっぱ、C++の規格に沿った処理を行うコンパイラーを使わないと
コンパイラーによって、結果が変わってしまうと思います。
#VC++はC++の規格と違うところが多いみたいだし......

Ban 2009/05/23(土) 01:38:14
C++の規格に一番近い処理を行うコンパイラーってやっぱGCCですかね?

使ってる感覚でいえば、一長一短というか、GCCはVCと大差ない感触です。

C++の言語仕様って「処理系定義」(コンパイラが決めていい)とか
異常に多いので、一番近いとかあまり意味ないかと。
評判という意味ではComeau C++とかも高いですね。


> やっぱ、C++の規格に沿った処理を行うコンパイラーを使わないと
> コンパイラーによって、結果が変わってしまうと思います。

考え方が違います。「C++の規格で『処理系で決めていいよ』」なわけで、
規格にどんなに沿っていようが、コンパイラが二種類あれば結果が変わるのは
ある意味で当然です。
そもそもinlineについては、極論パースさえ正しくできれば、
全部無視してinline展開まったくしなくても規格に完全合致ですから
全く関係ない。同じ結果をそこに期待するのが間違いかと。>C++


> #VC++はC++の規格と違うところが多いみたいだし......

VC7.1あたりで自称準拠率99%です。実際、この頃でかなり改善してます。
対応する気が毛頭ないexportとかを除けば、
昨今のVCは有数の準拠率を誇る実用的なコンパイラだと思いますよ。

# 言語仕様が決まりきる前の遺物=VC6が蔓延してたのがその風評の元かと。
# VC6とかBCC5.5とかC++コンパイラとしてはもうむりぽ…

古いスレッドには追加発言できません。