2012-04-23 9 views
3

すべてのコード私が読んだことから、A1 & A2は同じですが、A3がA2と同じ場合はありません。私はすべてのAクラスが作成されているので、コードがコンパイルされることを知っています。関数がヘッダファイルで定義されている場合、インラインキーワードは意味がありますか?

注:クラス&のメソッド宣言はすべて、.hファイルにあります。

template <typename _Ty> 
class A1 { 
public: 
    A1(); 
    void foo() { ... } 
}; 


template <typename _Ty> 
class A2 { 
public: 
    A2(); 
    void foo(); 
}; 

template <typename _Ty> 
inline void A2<_Ty>::foo() { ... } 


template <typename _Ty> 
class A3 { 
public: 
    A3(); 
    void foo(); 
}; 

template <typename _Ty> 
void A3<_Ty>::foo() { ... } // note: No inline keyword here. 

P.S.私はstackoverflowでこの質問の変種を見てきましたが、この正確な質問ではありません。

+0

'inline'はコンパイラにとっては「オプション」なので、*インラインには何もありません**キーワードは単なる**インライン化できるコンパイラ**です。 –

+1

@TonyTheLion:私は彼が実際のインライン化に本当に関わっているのではなく、C++で 'inline'を本当に使用していると思います。複数の翻訳単位で表示されている場合、ODRを破ることはありません。 –

+0

@TonyTheLion:**インラインキーワードを指定する**の場合があります。私の答えを見てください。 – SigTerm

答えて

8

はい、意味がありますが、テンプレートと組み合わせても効果はありません。

inlineキーワードの主な効果は、この関数が複数のコンパイル単位で同じ定義で表示される可能性があることをコンパイラに伝えることです。そのため、リンカーに対して「選択1」としてフラグを立てる必要があります複数の定義エラーを取得する)。テンプレートにはすでにこの機能があります。

inlineは、関数をインライン化する必要があると考えているコンパイラのヒントですが、コンパイラは通常、最適化を独自にインライン化する最終決定を行います。

+0

しかし、良いコンパイラは、決定を下す際に関数が 'inline'宣言されているかどうかを判断します。そうしない理由は、プログラマーよりもコンパイラーが実際にこの決定を下す方が優れているということです。それは私が知っているコンパイラーではまだありません。 –

+0

@ジェームズ:だから私は "何も効果がない"の代わりに "多くの*効果がない"と言ったのです。 –

+0

@JamesKanze:もちろん最良の方法は絶対ありませんが、コンパイラは、ヒューリスティックを使ってインライン展開が努力に値するかどうかを判断します(http://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html - > grep for "ヒューリスティック")。フォースインライン化は実際にディープ最適化ウィザードリッジの問題であり、投機的/非順不同実行、プリフェッチ、キャッシュ階層、分岐ターゲットバッファ、キャッシュサイズなど、多くのトピックの知識が必要です。コンパイラは、 99%のプログラマー –

0

関数がヘッダファイルで定義されている場合、インラインキーワードは意味がありますか?

です。


main.cppに

#include "a.h" 

int main(int argc, char** argv){ 
    A obj; 
    obj.f(); 
    a(); 
    b(); 
    return 0; 
} 

ああ

#ifndef A_HEADER 
#define A_HEADER 

class A{ 
public: 
    void f(); 
}; 

void a(){ 
} 

void b(); 

void A::f(){ 
} 

#endif 
次のプロジェクトは、インラインキーワードの省略のMSVCとg ++の両方にリンカエラーが生成されます

b.cpp

#include "a.h" 

void b(){ 
    A obj; 
    obj.f(); 
    a(); 
} 

(Qtの4ビルドシステム用)* .PROファイル:

TEMPLATE = app 
TARGET = 
DEPENDPATH += . 
INCLUDEPATH += . 

HEADERS += a.h 
SOURCES += b.cpp main.cpp 

コンパイル出力

cl。exeファイル:


main.obj : error LNK2005: "void __cdecl a(void)" ([email protected]@YAXXZ) already defined in b.obj 
main.obj : error LNK2005: "public: void __thiscall A::f(void)" ([email protected]@@QAEXXZ) already defined in b.obj 
debug\1234.exe : fatal error LNK1169: one or more multiply defined symbols found 

グラム++:今


debug/main.o: In function `Z1av': 
D:\c++\1234/a.h:6: multiple definition of `a()' 
debug/b.o:D:\c++\1234/a.h:6: first defined here 
debug/main.o:D:\c++\1234/a.h:11: multiple definition of `A::f()' 
debug/b.o:D:\c++\1234/a.h:11: first defined here 
collect2: ld returned 1 exit status 
make[1]: *** [debug/1234.exe] Error 1 
make: *** [debug] Error 2 

、なぜあなたはこれが起こると思いますか?コンパイラは、コンパイル時にヘッダファイルの内容をの内容を* .cppファイルに挿入するためです。関数は "インライン"ではないので、その名前はリンカーに知らされ、それぞれ.obj/ .oファイルはA::f()a()という固有のコピーを取得します。リンカはあなたが使用するはずのものを知らず、不平を言うでしょう。関数をインライン化すると、すべて正常に動作します。

しかし、テンプレートは別の話です。

+0

duplicate of http://stackoverflow.com/a/1759575/103167テンプレート以外の場合については既に他の質問でよく説明されています。 –

関連する問題