インライン関数プロトタイプ対正規宣言対プロトタイプ

インライン関数とmainの違いは何ですか?

inline double cube(double side)
{
   return side * side * side;
}

int main( )
{
    cube(5);
}

定期的に以下のような関数を宣言するだけです:

double cube(double side)
{
   return side * side * side;
}

int main( )
{
    cube(5);
}

関数プロトタイプ対?

double cube(double);

int main( )
{
    cube(5);
}

double cube(double side)
{
   return side * side * side;
}
3
追加された 著者 Kerrek SB,
cube(5); を意味しましたか?
追加された 著者 log0,
私はそう思った。
追加された 著者 log0,

4 答え

インライン関数は、複数の翻訳単位(cppファイル+インクルード)で定義することができ、関数をインライン化するためのヒントです。これは通常、ヘッダーに置かれ、コンパイル時間は長くなりますが、より速いコードに導くことができます。 また、多くのコンパイル単位から関数を使用することができます。

//cube.h
inline double cube(double side)
{
   return side * side * side;
}

//cube.cpp
int main( )
{
    cube(5);
}

それを定期的に定義するのが通常の方法です(通常はcppファイルで定義され、リンクされています)。他のコンパイル単位からは簡単には使用できません。

//cube.cpp
double cube(double side)
{
   return side * side * side;
}

int main( )
{
    cube(5);
}

プロトタイプを使うと、たとえまだ存在しないとしても、リンク時に関数が存在することをコンパイラに伝えることができます。これにより、メインがまだ存在していなくても、関数を呼び出すことができます。一般に、プロトタイプはヘッダーにあります。したがって、他のコンパイル単位は、それ自体を定義することなく関数を呼び出すことができます。これはコンパイル時間が最も速く、この機能は他のコンパイル単位から簡単に使用できます。

//cube.h
double cube(double);

//cube.cpp
int main( )
{
    cube(5);
}

double cube(double side)
{
   return side * side * side;
}
6
追加された
優秀かつ非常に理解できる説明、卿/奥さん。どうもありがとう!
追加された 著者 iggy2012,
最後の例は、 cube.hcube.cpp と別の翻訳単位の両方に含まれている場合、診断不要で未定義の動作です。関数は、あるユニットではインラインでなく、別のユニットではインラインでないことがあります。
追加された 著者 M.M,
2番目の例では、プロジェクトの他の部分も cube という関数を作成した場合に、意図しない未定義の動作を避けるために関数を内部リンケージとしてマークすることをお勧めします。
追加された 著者 M.M,
...単一のコンパイル単位(cppファイル+インクルード)に複数回定義できます - 異なるコンパイル単位を意味しましたか?
追加された 著者 anatolyg,
@MooingDuck:anatolygが正しく、ODRに違反することなくプログラム内で複数回定義できる場合でも、インライン関数は翻訳ユニットで一度定義することができます。
追加された 著者 David Rodríguez - dribeas,
いいえ、 inline はテンプレートのようにODRに違反することが許されています。さもなければ、ヘッダーにインラインを置くのは難しいだろうし、ヘッダーになければ、愚かなコンパイラーはそれをインライン化できないだろう!
追加された 著者 Mooing Duck,
ああ、私は間違っていた。インクルードガードを忘れてしまった。
追加された 著者 Mooing Duck,
@ M.M:最後のサンプルで、余分な inline を修正しました。ありがとうございます。あなたは内部のリンケージについては正しいですが、それは答えには関係ない超複雑さです。
追加された 著者 Mooing Duck,
なぜこれは私が不思議な答えとして受け入れられないのですか?
追加された 著者 Felype,

パフォーマンス上の理由から、 inline はコンパイラのヒントにすぎないので、これらはすべて同じです。宣言/定義の分離が使用され、その定義が別の変換単位にある場合、コンパイラーがインライン化するのは難しくなります(ただし、そのような実装があります)。

関数 inline を作ることとの違いは、リンカーが関数に対して同じインライン定義を2回以上見ても不平を言ってこないということです。

1
追加された

3つのプログラムは g ++ -S -O3 $ file.cc で全く同じようにコンパイルされます。 int main()にインライン展開されていても、 double cube(double side)の定義がまだインラインではない形式で存在する2番目の例を除きます。

_main:
pushl   %ebp
movl    $16, %eax
movl    %esp, %ebp
subl    $8, %esp
andl    $-16, %esp
call    __alloca
call    ___main
leave
xorl    %eax, %eax
ret
1
追加された
あなたが指摘している相違点は実装の詳細ですが、コンパイラによっては、 inline 関数のアドレスを取得することが許可されているため、実際にインライン化されていても常にすべての関数が生成されます。後で同じTU内で関数のアドレスが要求された場合に関数を処理している間に知っている。
追加された 著者 David Rodríguez - dribeas,
@Davidまさに。
追加された 著者 log0,

関数をインラインで宣言すると、コンパイラは関数の本体を呼び出される場所に多かれ少なかれコピーすることで、コードを高速化しようとします。それは唯一の示唆であり、それが可能であれば、コンパイラによる決定を下すことです。

私は第3の例で何が起こるのか分かりません。私はそれが使用されているツールチェーンに依存すると思います。

0
追加された
最後のものはmain()の前の単なる関数プロトタイプです。それらはすべて同じように動作するようですが、違いは何か分かりません。
追加された 著者 iggy2012,