9

最小限のコード:

// --------inline.h--------
struct X { 
  static inline void foo ();
};   
#ifdef YES
inline void X::foo () { cout << "YES\n"; }
#else
inline void X::foo () { cout << "NO\n"; }
#endif

// --------file1.cpp--------
#define YES    // <---- 
#include"inline.h"
void fun1 ()
{
  X::foo();
}

// --------file2.cpp--------
#include"inline.h"
void fun2 ()
{
  X::foo();
}

andを呼び出すfun1()fun2()、それぞれYESandが出力さNOれます。これは、同じ の異なる関数本体を参照していることを意味しますX::foo()

これをコード化する必要があるかどうかに関係なく、私の質問は次のとおり
です。これは明確に定義された動作ですか、それとも未定義の動作ですか?

4

3 に答える 3

13

はい、未定義の動作です。

参照:

C++03 標準:

7.1.2 関数指定子 [dcl.fct.spec]
パラ 4:

インライン関数は、それが使用されるすべての翻訳単位で定義され、すべての場合でまったく同じ定義を持つものとします (3.2)。[注: インライン関数の呼び出しは、その定義が翻訳単位に表示される前に発生する場合があります。] 外部リンケージを持つ関数が 1 つの翻訳単位でインライン宣言されている場合、それが現れるすべての翻訳単位でインライン宣言されなければなりません。診断は必要ありません。外部リンケージを持つインライン関数は、すべての翻訳単位で同じアドレスを持つ必要があります。extern インライン関数の静的ローカル変数は、常に同じオブジェクトを参照します。extern inline 関数の文字列リテラルは、異なる翻訳単位の同じオブジェクトです。

注: 3.2 は One Definition Rule を指し、次のように述べています。

3.2 1 つの定義規則 [basic.def.odr]
パラ 1:

変換単位には、変数、関数、クラス型、列挙型、またはテンプレートの複数の定義が含まれてはなりません。

于 2012-06-26T04:46:11.750 に答える
7

未定義。ODR に違反しています。

于 2012-06-26T04:38:58.760 に答える
4

fun1() と fun2() を呼び出すと、それぞれ YES と NO が出力されます。これは、同じ X::foo() の異なる関数本体を参照していることを意味します。

試してみましたか?異なる最適化レベルで?

最適化レベルと、コンパイルされたオブジェクトがリンカーに提示される順序に応じて、YES と NO、YES と YES、または NO と NO を取得します。

言うまでもなく、これは未定義の動作です。

于 2012-06-26T05:05:12.327 に答える