news 2026/7/18 0:46:11

C++编程实践——模板的显式实例化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
C++编程实践——模板的显式实例化

一、说明

模板的显式实例化,explicit instantiation,也叫全实例化。所谓显式实例化,就是开发者为模板代码(模板函数或类)手动编写指定类型的代码。类似下面的代码:

template<typename T>TDemo(T a){returna;}templateintDemo<int>(int);template std::string Demo<std::string>(std::string);

大家一定要把显式实例化和全特化区分出来,一个最简单的方法是,显式实例化的template后不再跟着模板尖括号“<>”,而所有的模板和特化(不管是偏特化和全特化)都是要有的。看一下全特化的情况:

template<typename T>TDemo(T a){returna;}template<>intDemo(inta){returna;}

也可以理解为全实例化只需声明不用自写实现而全特化需要自己实现相关的代码。当然,模板类也是如此实现的,此处不再给出例子。

二、显式实例化和隐式实例化

C++模板默认的是使用的隐式实例化即Implicit Instantiation,由于模板通常是定义在头文件中的,所以在实际生成代码中,会生成多个实例,这就需要编译器和链接器在实际的处理中进行去重的处理。而显式实例化则直接给出了模板最终的生成形式,并由编译器最终生成代码。这种情况下,基本等同于一个明确的模板实现代码(类或函数),或者说最终形成的代码已经可以不认为是模板代码了。这就出现了一个问题,如果其在头文件中,则必然产生重复定义的结果。所以,显式实例化的代码必须在cpp文件中,这是与普通模板代码一般在头文件中的一个最明显的不同。
而从编译器的角度来看,显式实例化由于在cpp文件中,一则避免了编译器对普通模板代码在头文件中编译导致的代码膨胀的问题;二则也解决了链接器中的去重处理。

三、应用场景和注意点

一般来说,显式实例化的应用非常广泛,不过也只是对模板开发来说。其主要的应用场景为:

  1. 库和框架的开发
    其实大家非常容易理解,由于模板开发的复杂性和难度,一般都是在底层框架中应用,最典型的就是STL和BOOST之类的库中。
  2. 有针对性的控制模板的应用类型
    这个可以理解,在对外的接口或应用中,可以将特定类型指定为应用类型
  3. 特定代码优化
    比如某些库或模板代码需要减少模板的代码膨胀和提高链接效率(去重)等
  4. 支持新标准
    如C++11后的外部模板,extern template。关于外部模板,前面分析过,此处不再展开

需要注意的是,使用显式实例化,必须优先定义普通模板,即显式实例化的模板必须可以在编译期搜索到普通模板的定义,否则会报编译错误;另外其不适用于局部类和匿名类(这也符合模板开发的要求)。

四、例程

下面给出一个简单的例程,然后将其显式实例化的代码编译出来:

#include<string>template<typename T>Tadd(T a,T b){returna+b;}templateintadd<int>(int,int);templatefloatadd<float>(float,float);intmain(){std::string s1="1";std::string s2="2";std::string s=add(s1,s2);return0;}

编译后的代码是:

#include<string>template<typename T>Tadd(T a,T b){returna+b;}/* First instantiated from: insights.cpp:6 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>intadd<int>(inta,intb){returna+b;}#endif/* First instantiated from: insights.cpp:7 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>floatadd<float>(floata,floatb){returna+b;}#endif/* First instantiated from: insights.cpp:11 */#ifdefINSIGHTS_USE_TEMPLATEtemplate<>std::basic_string<char>add<std::basic_string<char>>(std::basic_string<char>a,std::basic_string<char>b){returnstd::operator+(a,b);}#endifintmain(){std::basic_string<char>s1=std::basic_string<char>("1",std::allocator<char>());std::basic_string<char>s2=std::basic_string<char>("2",std::allocator<char>());std::basic_string<char>s=add(std::basic_string<char>(s1),std::basic_string<char>(s2));return0;}

在上面的代码和编译后的代码进行对比可以看出来,显式实例化的代码会自动生成指定数据类型的模板实例(具现)化的代码。大家可以将模板类也以上面的形式进行处理一下,看最终的代码会是什么样。给出一个小例子,可以在此代码基础上完善:

template<typename T>class Example{public:voidadd(constT&x){};voidcount(){};};// 显式实例化template class Example<int>;template class Example<char>;

五、总结

模板的学习对于开发者来说不是一个一蹴而就的问题,需要开发者不断的将书本知识与实践反复融合。而且,随着C++最新的标准不断的完善,针对模板的相关内容(如概念等)和技术也在不断的完善,这就对开发者提出了更高的要求。不过,不要着急,休息一下,休息一下。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/17 21:04:16

揭秘Open-AutoGLM内测资格:如何在48小时内成功申请并上手实操

第一章&#xff1a;揭秘Open-AutoGLM内测申请的核心价值为何参与内测至关重要 Open-AutoGLM作为新一代开源自动代码生成语言模型&#xff0c;其内测阶段不仅是技术验证的关键窗口&#xff0c;更是开发者提前掌握AI编程范式演进方向的战略机遇。通过参与内测&#xff0c;开发者能…

作者头像 李华
网站建设 2026/7/14 2:49:07

31、Git 操作与服务器搭建全攻略

Git 操作与服务器搭建全攻略 1. Git 基本操作 在 Git 的使用过程中,我们常常会遇到需要撤销更改、移动文件、恢复历史版本等情况。下面详细介绍这些操作的具体方法。 1.1 撤销暂存更改 当你已经将更改添加到暂存区,但又想撤销这些操作时,可以使用 git reset 命令。例如…

作者头像 李华
网站建设 2026/7/14 15:10:54

34、无服务器时的在线代码托管与项目管理工具推荐

无服务器时的在线代码托管与项目管理工具推荐 在软件开发过程中,代码托管和项目管理是非常重要的环节。当你没有自己的服务器时,有许多在线工具可供选择。下面为你详细介绍几款实用的工具。 Springloops Springloops 是一款功能强大的工具,为开发者提供了多种实用特性。 …

作者头像 李华
网站建设 2026/7/14 3:24:36

GPT-SoVITS适合儿童声音克隆吗?安全性分析

GPT-SoVITS适合儿童声音克隆吗&#xff1f;安全性深度解析 在AI语音技术飞速发展的今天&#xff0c;你有没有想过&#xff1a;一个孩子只需朗读一分钟&#xff0c;AI就能“学会”他的声音&#xff0c;并用这个音色讲出任何你想听的故事&#xff1f;这听起来像是科幻电影的情节&…

作者头像 李华
网站建设 2026/7/14 6:43:14

GPT-SoVITS在播客行业的颠覆性应用前景

GPT-SoVITS在播客行业的颠覆性应用前景 在音频内容爆发式增长的今天&#xff0c;播客已不再是小众爱好者的自留地&#xff0c;而是成为品牌传播、知识输出和情感连接的重要媒介。然而&#xff0c;一个现实问题始终困扰着创作者&#xff1a;高质量语音内容的生产成本太高了。专…

作者头像 李华
网站建设 2026/7/13 17:13:37

如何高效管理IT资产?

在工作中&#xff0c;最头疼的事情之一&#xff0c;就是老板突然问一句&#xff1a;“咱们现在到底有多少台设备&#xff1f;咱们监控的覆盖率怎么样&#xff1f;&#xff1f;” 面对成百上千、甚至跨多个网段的IP地址&#xff0c;手工去梳理和登记资产信息&#xff0c;不仅工作…

作者头像 李华