模板导致的代码膨胀
2007-03-30 20:10
190 查看
模板是一种源码复用技术,在某些情况下使用它可以使代码看起来非常优雅,著名的boost库就是模板发扬的典范.
然而模板也存在弊端,大量使用模板可能导致代码膨胀.下面介绍一种解决的方案:
我们首先看一段一般代码:
template < typename T >
class Vector
{
public :
virtual void Say()
{
const type_info & t = typeid(T);
std::cout << " Vector< " << t.name() << " >::Hello " << std::endl;
}
} ;
// 特例化
template <>
class Vector < void *>
{
public :
virtual void Say()
{
std::cout << " Vector<void*>::Hello " << std::endl;
}
} ;
int _tmain( int argc, _TCHAR * argv[])
{
Vector < int *> pIntVec;
pIntVec.Say();
Vector < double *> pDoubleVec;
pDoubleVec.Say();
return 0 ;
}
输出:
Vector<int *>::Hello
Vector<double *>::Hello
从这里,我们可以看出程序在运行的过程中生产了两分Vector的代码(int*和double*),尽管这里有特例化,然而类型不匹配,编译器在编译过程中无法定位到特例化版本.如果这个Vector被滥用,即使是一个中等规模的程序也可能耗费成兆字节的代码控件.
我们必须寻找一种中间桥梁使编译器在编译过程中定位到void*的特例化版本.按照模板选择策略,编译器总是选择最特例化的模板,我们可以通过一个中间的模板联系起上面两个版本的模板.下面看一段代码:
template < typename T >
class Vector
{
public :
virtual void Say()
{
std::cout << " Vector::Hello " << std::endl;
}
} ;
// 特例化
template <>
class Vector < void *>
{
public :
virtual void Say()
{
std::cout << " Vector<void*>::Hello " << std::endl;
}
} ;
// 特例化
template < typename T >
class Vector < T *> : public Vector < void *>
{
} ;
int _tmain( int argc, _TCHAR * argv[])
{
Vector < int *> pIntVec;
pIntVec.Say();
Vector < double *> pDoubleVec;
pDoubleVec.Say();
return 0 ;
}
输出:
Vector<void*>::Hello
Vector<void*>::Hello
从这里,我们可以看出程序在运行过程中全部使用Vector<void*>的版本.class Vector<T*>模板便是关键的环节.编译器在编译过程中,由于class Vector<T*>比class Vector更特例化,所以遇到Vector<int*>和Vector<double*>时都选择class Vector<T*>,而class Vector<T*>继承Vector<void*>,一个更加特例化版本,所以编译器不再产生新的模板而采用 Vector<void*>这个最特例化版本,这样所有指针模板都归结到Vector<void*>,而class Vector<T*>为用户提供了一个精美而且安全的界面,而Vector<void*>作为底层实现细节被隐藏.
然而模板也存在弊端,大量使用模板可能导致代码膨胀.下面介绍一种解决的方案:
我们首先看一段一般代码:
template < typename T >
class Vector
{
public :
virtual void Say()
{
const type_info & t = typeid(T);
std::cout << " Vector< " << t.name() << " >::Hello " << std::endl;
}
} ;
// 特例化
template <>
class Vector < void *>
{
public :
virtual void Say()
{
std::cout << " Vector<void*>::Hello " << std::endl;
}
} ;
int _tmain( int argc, _TCHAR * argv[])
{
Vector < int *> pIntVec;
pIntVec.Say();
Vector < double *> pDoubleVec;
pDoubleVec.Say();
return 0 ;
}
输出:
Vector<int *>::Hello
Vector<double *>::Hello
从这里,我们可以看出程序在运行的过程中生产了两分Vector的代码(int*和double*),尽管这里有特例化,然而类型不匹配,编译器在编译过程中无法定位到特例化版本.如果这个Vector被滥用,即使是一个中等规模的程序也可能耗费成兆字节的代码控件.
我们必须寻找一种中间桥梁使编译器在编译过程中定位到void*的特例化版本.按照模板选择策略,编译器总是选择最特例化的模板,我们可以通过一个中间的模板联系起上面两个版本的模板.下面看一段代码:
template < typename T >
class Vector
{
public :
virtual void Say()
{
std::cout << " Vector::Hello " << std::endl;
}
} ;
// 特例化
template <>
class Vector < void *>
{
public :
virtual void Say()
{
std::cout << " Vector<void*>::Hello " << std::endl;
}
} ;
// 特例化
template < typename T >
class Vector < T *> : public Vector < void *>
{
} ;
int _tmain( int argc, _TCHAR * argv[])
{
Vector < int *> pIntVec;
pIntVec.Say();
Vector < double *> pDoubleVec;
pDoubleVec.Say();
return 0 ;
}
输出:
Vector<void*>::Hello
Vector<void*>::Hello
从这里,我们可以看出程序在运行过程中全部使用Vector<void*>的版本.class Vector<T*>模板便是关键的环节.编译器在编译过程中,由于class Vector<T*>比class Vector更特例化,所以遇到Vector<int*>和Vector<double*>时都选择class Vector<T*>,而class Vector<T*>继承Vector<void*>,一个更加特例化版本,所以编译器不再产生新的模板而采用 Vector<void*>这个最特例化版本,这样所有指针模板都归结到Vector<void*>,而class Vector<T*>为用户提供了一个精美而且安全的界面,而Vector<void*>作为底层实现细节被隐藏.
相关文章推荐
- 防止模板代码膨胀
- 没有模板代码膨胀的STL:四、一些讨论和个人心得
- 下面哪些特性可能导致代码体积膨胀:----腾讯2016研发工程师在线模拟笔试题
- template实例化导致代码膨胀的后果(编译器编译才20行的代码就死掉哦)
- phpcms审核代码处理存在bug导致审核过无变化/模板基于审核状态将误判问题
- keil中对struct结构体静态赋值导致代码急剧膨胀的原因(转)
- Effective C++第七章-模板和泛型编程之模板特化和代码膨胀
- 深入分析:C++模板究竟会使代码膨胀吗
- C++模板会使代码膨胀吗
- 没有模板代码膨胀的STL:一、设计目标与实现思路
- 没有模板代码膨胀的STL:二、使用方法与注意事项
- thinkcmf5更新模板代码分析,解决模板配置json出错导致数据库保存的配置项内容丢失问题
- 没有模板代码膨胀的STL:三、开发者指南
- 为什么C++编译器不支持模板头文件和实现代码分离的编译
- netbeans 新建代码模板
- 使用T4 模板来自动生成WCF 代理类 代码
- 代码注释模板
- jsp文件做模板文件生成代码
- 23个phpcms v9模板制作及二次开发常用代码案例
- Freemarker模板自动生成java代码