我曾经在一次求职面试中被问到一个棘手的问题:一个模板化的类是否比另一个相同但没有模板化的类占用更多的内存?我的回答是否定的,但他问这个问题的事实意味着可能存在这种情况。或者,他真的想和我搞砸。什么情况下模板类会占用更多内存?
3 回答
首先要明确问题的含义。如果问题是该类型的对象是否会更大(即sizeof(T<int>) > sizeof(T_int)
),那么答案是否定的。如果问题是关于应用程序本身的二进制足迹,包括函数的代码,那么答案是程序的整体大小在模板的情况下实际上可能更小,因为只会编译使用的成员函数(除非显式实例化)。尽管在一天结束时,链接器也可能会从非模板版本中丢弃未使用的成员。
有一个通用术语:代码膨胀,用于指代模板生成的代码的爆炸式增长。该术语指的是模板的每个不同实例化都将生成其自己的函数,并且与允许转换参数的较小的非模板函数集相比,这可能导致可执行文件中存在更多的函数。
考虑一个向量模板的可能接口:
template <typename T>
class Vector {
template <typename U> void push_back(U u);
//....
对于每个push_back
使用不同参数类型的调用,都会生成一个新函数,因此会有一个 forVector<int>::push_back('a')
和另一个 for 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;
....
}
所以它基本上与任何其他非模板类的大小相同。