就職の面接でひっかけ質問をされたことがあります: テンプレート化されたクラスは、同じであるがテンプレート化されていない別のクラスよりも多くのメモリを消費しますか? 私の答えはノーでしたが、彼が質問したということは、おそらくある場合があるということです。または、彼は本当に私を台無しにしたかったのです。テンプレート化されたクラスがより多くのメモリを消費するケースはどのようなものでしょうか?
3 に答える
まず、質問の意味を明確にすることです。タイプのオブジェクトが大きくなるかどうか (つまりsizeof(T<int>) > sizeof(T_int)
) が問題である場合、答えはノーです。関数のコードを含む、アプリケーション自体のバイナリ フットプリントに関する質問の場合、答えは、テンプレートの場合、使用されるメンバー関数のみがコンパイルされるため、プログラムの全体的なサイズが実際には小さくなる可能性があるということです (明示的にインスタンス化されていない限り)。結局のところ、リンカーは非テンプレート バージョンからも未使用のメンバーを破棄する可能性があります。
テンプレートによって生成されるコードの急増を指す一般的な用語があります。コードの膨張です。この用語は、テンプレートのそれぞれの異なるインスタンス化が独自の関数を生成し、引数の変換が許可されている非テンプレート関数の小さなセットを持つよりも多くの関数が実行可能ファイルに存在する可能性があるという事実を指します。
ベクター テンプレートの可能なインターフェイスを考えてみましょう。
template <typename T>
class Vector {
template <typename U> void push_back(U u);
//....
異なる引数の型で を呼び出すたびpush_back
に、新しい関数が生成されるため、 用の関数と 用Vector<int>::push_back('a')
の別の関数がありVector<int>::push_back(1)
ます。std::vector
メンバー関数がテンプレートではなく、呼び出し元が型変換を行うインターフェイスと比較してください。
これはより大きな実行可能ファイルのソースになる可能性がありますが、これが求められたものであるとは考えていません。特に、テンプレート化された型、および特定のインスタンス化された型用に手作りされた同等の非テンプレート型の場合、生成されたコードは同等である必要があります (マングルされた名前はテンプレートの方が大きくなる傾向があるという事実を無視します:))
メモリに関する限り、答えはノーです。つまり、必ずしもより多くのメモリを必要とするわけではありませんが、クラス テンプレートのバージョンがより多くのメモリを必要とするという彼の主張を証明するためだけに、悪者がクラス テンプレートを作成する可能性があります。
ただし、クラス テンプレートのソース コードは、型パラメーターの特定の値の非テンプレート クラス バージョンよりも大きい (または小さい) 可能性があります。
template<typename T>
struct point_t
{
T x, y, z;
};
struct point_int
{
int x, y, z;
};
std::cout << (sizeof(point_int) == sizeof(point_t<int>)) << std::end;
true
(または)が印刷されます1
。
と のメモリ レイアウトは同じpoint_int
にpoint_t<int>
なることに注意してください。したがって、次のようにキャストすることもできます。
point_t<int> pt {10, 20, 30};
point_int pi = *reinterpret_cast<point_int*>(&pt);
std::cout << "{" << pi.x <<"," << pi.y <<"," << pi.z << "}" << std::endl;
印刷されます{10, 20, 30}
。
それが役立つことを願っています。
テンプレートは、コンパイル時に参照されるすべての場所で実際の値に置き換えられます。テンプレートクラスがある場合は、次のように言います。
public List<T>
{
public T* MyT;
...
}
そして、あなたのコードはそれを特定のタイプで使用します: List 、このコードが使用されている実際に起こっていることよりも:
public List<Point>
{
public Point *MyT;
....
}
そのため、他の非テンプレート クラスと本質的に同じサイズです。