11

私が理解していることから、たとえば、とがあればstd::vector<int>std::vector<float>コンパイラはタイプごとに1つずつ、2つのクラスを作成します。したがって、記述されるコードの量は減りますが、実行可能ファイルのサイズは減りません(間違っている場合は訂正してください)。

タイプがポインタであっても同じですか?たとえば、とをインスタンス化するstd::vector<SomeClass*>と、std::vector<SomeOtherClass*>必然的にコンパイラは2つのインスタンス化のそれぞれに対して個別のコードを生成しますか?

4

5 に答える 5

6

これは、実装に依存するas-if最適化であるため、許可されています。

実際、これはコンパイラーが行う必要はありません。標準ライブラリはそのように実装できます。たとえば、実装はすべてを使用std::is_pointerしてから、すべてを単一void*ベースの実装に延期することができます。(これはシンテンプレートイディオムです)。実際、ライブラリ側でこれを行うことは、コンパイラがコードをインスタンス化した後にマージするよりも実行可能であるように見えますが、それも可能です。

于 2012-12-17T12:53:11.497 に答える
5

コンパイラは、プログラムが使用する数のクラスをテンプレートからインスタンス化します。ただし、実行可能ファイルに入れるために生成されたコードは、プログラムに存在するクラスとは少し異なります。

実際には、上のほとんどの操作vectorはインライン化されます。したがって、実行可能ファイルのサイズは、そのテンプレートからインスタンス化されるさまざまなクラスの数に応じてあまり変化しない可能性があります。これは、コードサイズの大部分が、個別のクラスごとではなく、関数呼び出しサイトごとであるためです。しかし、それがインスタンス化の数に依存する限り、vector<SomeClass*>そしてvector<SomeOtherClass*>異なるクラスです。

の明示的なインスタンス化を行うとvectorすべてのメンバー関数がクラスに対して生成されます。あなたがそれを探すならば、あなたはおそらくコードサイズのその違いを見るでしょう。ただし、通常はテンプレートクラスを明示的にインスタンス化しないため、使用するメンバー関数のみが生成されます。

于 2012-12-17T12:28:01.647 に答える
4

結果の動作が正しい場合、コンパイラはテンプレートの両方のインスタンス化を実装する単一のコードセットを生成することができます。これは、ポインター型と非ポインター型で発生する可能性があります。これは、テンプレートクラスのルーチン(別名「メソッド」)ごとに独立して発生する可能性があります。

これがいつ発生するかを判断するのは難しい場合があり、コンパイラーはそうする機会を認識する場合と認識しない場合があります。

たとえば、代入演算子が通常行うように、ルーチンが単にクラスをコピーする場合、クラスデータが同じサイズであるテンプレートのインスタンス化に同じコードを使用できる可能性があります。一部のプロセッサでは、 2つのintオブジェクトを追加するコードは、オブジェクトに追加するコードと同じ場合があります。unsigned int

于 2012-12-17T12:34:03.037 に答える
4

はい、あなたが正しい。重複を軽減する方法があります。ダイエットテンプレートのプレゼンテーションのスライド18〜26を参照してください。

ある時点では、「常識」でstd::vector<T*>あり、std::vector<U*>両方とも特殊化の薄いラッパーとして実装できるvector_impl<void*>ため、可能な場合は同じ生成コードを共有します(これは、スライドでの巻き上げと呼ばれます)が、私は思いません最新のstd::lib実装は、実際にその最適化を行います。確かにlibstdc++はそうではありません。

于 2012-12-17T12:57:25.047 に答える
2

コンパイラは「2つのクラスを作成」しません。むしろ、std::vector<int>std::vector<float> 2つの異なるクラスです。クラスとテンプレートを混同しないでください—これらは言語のコアコンセプトです!同様にstd::vector<SomeClass *>std::vector<SomeOtherClass *>は2つの異なるクラスであり、質問に答える必要があります。

于 2012-12-17T12:20:13.290 に答える