2

私はC++標準のODRに関連する条項を読んで読み直しましたが、この質問はまだ私に開かれています。この規格では、インライン関数の定義は、それが使用されるすべての変換単位に表示される必要があり、定義は、ほぼ1ページに記載されている意味で同一である必要があります。トークンシーケンスは同じでなければならないということです。ローカル識別子名が含まれていますか?

言い換えれば、次のプログラムはODRに違反していますか?(Visual Studio 2008で自分でテストしようとすると、エラーと警告が0になりました。しかし、例を2つの完全に異なる定義に変更しても、エラーと警告が0になるため、これは何も証明されないと思います。 MSVCの言い訳として、ODRの違反に対して正式に診断を行う必要はないことに注意してください。

//main.cpp
inline int f(int);
int main(){
   f(3);
}
int f(int x){
   int z = x;
   return z*z;
}

//other.cpp
inline int f(int xx){
   int zz = xx;
   return zz*zz;
}
4

3 に答える 3

6

はい、ODRに違反しています。xはとは異なるトークンであるため、異なるトークンシーケンスを使用しますxx。それはそれと同じくらい簡単です。トークンではないため、異なる空白やコメントを含めることができます。

従来のコンパイルツールチェーンでは、翻訳ユニット全体でODRを検証することは困難または不可能です。標準では「診断は不要」と記載されているため、未定義の動作が発生します。

たとえば、無関係の翻訳単位で同じ名前で定義された2つの異なるクラスを使用すると、さらに微妙なエラーが発生する可能性があります。仮想テーブルがある場合、エラーメッセージなしで衝突する可能性があります。したがって、ローカル関数とクラスには常に匿名の名前空間を使用してください。

于 2010-11-28T15:33:11.550 に答える
3

識別子は一種のトークンであり、各識別子は個別のトークンであるため、そうです、ODRを尊重するには同じ識別子が必要です。これを検出するコンパイラに違いをもたらす可能性があります(エクスポートされたテンプレートを使用してcomoの例を作成する準備ができている人はいますか?ODRの違反を検出できます)。

次に、ここでCとC++の違いがあります。Cには一般にODRがなく、C99のインライン関数の規則(C90にはインライン関数はありません)はC++の規則とはかなり異なります。C99では、コードは正しいです。実際、まったく異なる定義を提供できます。結果として、C(C ++ではない)では、同じ定義を使用し、その定義に静的メンバーがある場合、実際には、関数を使用するTUと同じ数の静的変数があります。

于 2010-11-28T16:28:26.333 に答える
2

識別子はトークンであるため、トークンの同じシーケンス規則により、プログラムはODRに違反します。

于 2010-11-28T15:34:11.170 に答える