2013-02-07 2 views
15

私のプログラムに関数があり、コードのどこかに関数ポインタがあります。コンパイラがその関数をインライン化した場合、またはその関数に割り当てられた関数ポインタが存在することをコンパイラが認識し、インライン展開を避けるとどうなりますか。コンパイラが関数ポインタを介して呼び出される関数をインライン化するとどうなるのですか?

+2

Herb Sutterの[Inline Redux](http://www.drdobbs.com/inline-redux/184403879)を参照してください。 –

答えて

12

関数へのポインタが取得されると、コンパイラはその関数の行外本体を生成します。他のコールサイトでも機能をインライン化することは可能です。関数はそれを参照するすべてのTUで利用可能な定義を持っている必要がありますinlineをマークし、そしてこれらの定義は同一でなければなりません

注意。つまり、一部の通話サイトで機能をインライン化し、他の通話サイトとは別の場所に保つことは、完全に安全です。

+0

定義が同一ではない場合(ifdefコードなど)、リンカーは複数のバージョンの関数を取得しますか? 'インライン'はおそらく弱い記号としてリンカに見え、最初に出てくるものを手に入れますか? –

+6

@NicholasWilsonそれは不正なプログラムになります。 –

+2

@NicholasWilsonは、1つの定義ルールに違反し、定義された動作を持たないと明示的に呼び出されます。 –

4

まあ、それは確かに動作します。インライン展開がそれを防ぐ方法はわかりません。あなたは関数を直接呼び出すコードをいくつか持っているだけで、そこにインライン展開されているかもしれませんし、通常の関数と同じように関数ポインタを使ってコードを呼び出すコードもあります。

3

関数ポインタを使用してインライン化を防止する必要はありません。インライン化は、ケースバイケースで行われ、通常の関数本体と一緒に存在することができます。だから、ある場所で関数をインライン化し、別の場所で関数を呼び出すことができます。

したがって、コンパイラはインラインで関数ポインタの呼び出し可能な関数を生成し、生成することができます。

2

だけではなく、コンパイラのインライン「機能の他の呼び出し」を行いますが、それは実際に使用されている機能について十分に理解している場合には、関数ポインタ経由でも、インライン呼び出しをしてもよい、このような何か:

typedef void (*funcptr)(); 

void somefunc() 
{ 
    ... do stuff here ... 
} 

void indirection(funcptr *f) 
{ 
    f(); 
} 

void call_with_ptr() 
{ 
    funcptr f = somefunc(); 
    for(int i = 0; i < 100; i++) 
    { 
     indirection(f); 
    } 
} 

私はこれに似たコードを持っていて、間接参照をインライン化し、関数ポインタを使わずにsomefunc()を直接呼び出すようにしました。

しかし、もちろん、これは、コンパイラがコードから呼び出される関数で把握することができますを前提と - この場合には明らかであるが、関連するランタイムの決定があれば、それはそうではないことがあります。

関連する問題