2011-07-01 7 views
9

私は2つの.cppファイル、file1.cppとfile2.cppを持っており、std::vector<int>を使用しています。 file1.cppにint main(void)があるとします。私がfile1.oとfile2.oの両方にコンパイルし、2つのオブジェクトファイルを実行可能なELFバイナリにリンクした場合、私は32ビットのUbuntu Linuxマシンでコンパイルしています。テンプレートのC++オブジェクトファイル

  • リンカが私の最後のバイナリを作る、コードの重複があります:

    私の質問は、コンパイラとリンカがのstd ::ベクトルのシンボルをまとめる方法について?リンカはf1.oのコードのためのテンプレート化されたコードのセットを持っていますか?std::vectorとf2.oを構成するコードのstd::vectorコードの別のセットはありますか?

Iは、(私はg++ -gを使用)、私は私の最終的な実行可能な分解を見、そしてf1.oからコードが現れたが、私は、ベクトルのコンストラクタおよび他の方法のために生成されたラベルが明らかにランダムであったが見つかりました。私のためにこれを試みましたf2.oのコードと同じコンストラクタを呼び出したことになります。しかし、私は確信することはできませんでした。

リンカがコードの重複を防止している場合、どうしますか?それはテンプレートが何であるかを「知っている」必要がありますか?複数のオブジェクトファイルにわたって同じテンプレートコードの複数の使用に関するコードの重複を常に防止しますか?

答えて

8

テンプレートが何であるかは、name manglingによってわかります。オブジェクトの型は、コンパイラによってその名前でエンコードされ、リンカーは同じテンプレートの重複した実装をフィルタリングできます。

これはリンク時に行われ、コンパイルではありません。各.oファイルをリンクすることができ、後で必要となるものを取り除くことができないためです。リンカーは、どのコードが使用されていないか、どのテンプレートが重複しているかなどを決めることができます。これは、オブジェクトのシンボルリストに "Weak Symbols"を使用して行います:リンカーが複数回表示された場合、重複してリンクエラーが発生した場合は削除できません)。

+0

これはOPの質問のほとんどに対応していません。それは本当ですが、ここで何が尋ねられているのかは特に関係ありません。 – templatetypedef

+0

@templatetypedef - 私は違います。 *リンカがコードの重複を防ぐ場合、どうやってそれをしますか?テンプレートはどのようなものかを "知って"いなければなりませんか?リンカは名前のマングリングを通じて知っています。インラインコード - は重複していますが、リンカーはそれと関係がありません。 – littleadv

+0

@ littleadv-あなたはまったく正しいですが、リンカが名前のマングリングを使用する理由、テンプレート関数の名前がどのように正規の関数と異なるのか、リンカがどのバージョンを選択するかなどを決める答えはありません。私はこれがトピック外であるか間違っていると言っているのではなく、むしろ質問に対する答えをすでに知っていない限り、この答えが役に立たないとは思わない。 – templatetypedef

0

技術的には、「1つの定義ルール」のために1つだけがstd::vector<int>であるため、コードをリンクする必要があります。起こりうることは、実行時間を短縮するコードがインライン化されているが、より多くのコードを生成する可能性があるということです。

std::vector<int>を使用しているファイルとstd::vector<unsigned int>を使用しているファイルがある場合は、2つのクラスがあり、潜在的に重複したコードがあります。

もちろん、ベクターの作者は、特定の状況(例えば、複製を削除するPODタイプ)でいくつかの共通コードを使用するかもしれません。

+0

私はstd :: vector とstd :: vector の複製について心配していません。 「1つの定義ルール」とは何ですか? f1.oとf2.oの両方のコンパイル時にstd :: vector の定義が作成されていませんか? – Chris

+0

"1つの定義ルール"はオブジェクトファイルごとであり、別々のオブジェクトファイルの間には、ベクトルの2つの異なるインスタンスが使用されます。インライン化されたものは、リンカーによって処理され、複製されません。 – littleadv

+0

要するに、1つの定義ルールは、同一のテンプレートインスタンスが複数のコンパイルユニットに現れても、そのテンプレートインスタンスのただ1つの定義としてコンパイラにカウントされることを示しています。基本的に、C++には、テンプレートコードの余分なコピーを削除する特定の目的のために、コンパイルとオブジェクトコードのリンクの間にこの特別なステップがあります。 – SingleNegationElimination

関連する問題