当前位置: 首页 > wzjs >正文

提供做网站企业百度app交易平台

提供做网站企业,百度app交易平台,网站建设专项检查,中国机械加工网木材综合破碎机模板为什么要extern? 在 C 中,多个编译单元使用同一个模板时,是否可以不使用 extern 取决于模板的实例化方式(隐式或显式),以及你对编译时间和二进制体积的容忍度。 1. 隐式实例化:可以不用 ex…

模板为什么要extern?

在 C++ 中,多个编译单元使用同一个模板时,是否可以不使用 extern 取决于模板的实例化方式(隐式或显式),以及你对编译时间和二进制体积的容忍度。


1. 隐式实例化:可以不用 extern,但存在代价
如果多个编译单元(如 a.cppb.cpp)隐式实例化同一个模板(如 MyTemplate<int>),编译器会为每个编译单元生成一份相同的实例化代码。此时:
• 允许性:C++ 标准允许这种行为(ODR 规则,多份相同定义合法)。

• 代价:
• 编译时间增加:每个编译单元重复生成模板代码。
• 二进制体积膨胀:链接器最终合并时会保留一份代码,但中间目标文件(.o)体积可能增大。
• 潜在 ODR 风险:若不同编译单元的实例化上下文不同(如宏定义差异),可能触发未定义行为。

示例:

// a.cpp
#include "MyTemplate.h"
void foo() {MyTemplate<int> a; // 隐式实例化
}// b.cpp
#include "MyTemplate.h"
void bar() {MyTemplate<int> b; // 隐式实例化
}

• 编译后,a.ob.o 各有一份 MyTemplate<int> 代码,链接时保留一份。


2. 显式实例化:必须用 extern,否则链接错误
如果多个编译单元显式实例化同一个模板(如 template class MyTemplate<int>;),则:
• 不用 extern 的后果:每个编译单元都会生成该模板实例化的定义,导致链接时 重复定义错误。
• 必须使用 extern:在头文件中声明 extern template class MyTemplate<int>;,仅在一个编译单元显式实例化。

错误示例:

// a.cpp
template class MyTemplate<int>; // 显式实例化// b.cpp
template class MyTemplate<int>; // 显式实例化:重复定义!

• 链接时报错:multiple definition of MyTemplate<int>

正确做法:

// MyTemplate.h
extern template class MyTemplate<int>; // 声明外部实例化// MyTemplate.cpp
template class MyTemplate<int>; // 显式实例化(仅一次)

3. 性能与可维护性权衡

策略是否用 extern优点缺点
隐式实例化不需要代码简单,无需额外管理编译慢,二进制体积大
显式实例化 + extern必须用编译快,体积小,控制实例化行为需手动管理声明和实例化

4. 实际工程建议

  1. 高频使用模板(如基础容器):
    • 推荐显式实例化 + extern:显著减少编译时间和二进制体积。

    • 例如:项目中广泛使用的 Vector<int>,显式实例化并集中管理。

  2. 低频使用模板(如特殊场景的工具类):
    • 允许隐式实例化:简化代码维护,避免过度设计。

  3. 跨团队/库的模板:
    • 必须显式实例化 + extern:避免二进制冲突和不可控的实例化行为。


5. 示例:显式实例化的正确用法

// ----------------------
// MyTemplate.h
template <typename T>
class MyTemplate { /* ... */ };// 声明显式实例化由 MyTemplate.cpp 提供
extern template class MyTemplate<int>;// ----------------------
// MyTemplate.cpp
#include "MyTemplate.h"// 显式实例化实现
template class MyTemplate<int>;// ----------------------
// a.cpp
#include "MyTemplate.h"
void foo() {MyTemplate<int> a; // 使用 extern 声明,不生成代码
}// ----------------------
// b.cpp
#include "MyTemplate.h"
void bar() {MyTemplate<int> b; // 同上
}

总结
• 可以不用 extern 的情况:

所有编译单元均通过隐式实例化使用模板(接受编译时间和体积代价)。
• 必须用 extern 的情况:

需要显式实例化且跨多个编译单元共享实例化代码(否则链接错误)。

最终建议:对高频使用或公共库的模板,显式实例化 + extern 是最佳实践。

不用extern方案

在 C++ 中,如果在某个编译单元中对模板进行了显式特例化(explicit specialization),而其他编译单元未声明该特例化,则其他编译单元仍会生成通用模板的隐式实例化代码,导致重复代码。以下是详细分析:


1. 显式特例化的作用域
• 特例化的可见性:显式特例化默认仅在定义它的编译单元内有效。

• 其他编译单元的行为:若未声明该特例化,编译器会隐式实例化通用模板,生成重复代码。


2. 示例场景
假设有两个源文件 a.cppb.cpp,以及一个头文件 my_template.h

文件结构

// my_template.h
template <typename T>
class MyTemplate {
public:void foo() {}
};// a.cpp
#include "my_template.h"// 显式特例化 MyTemplate<int>
template <>
class MyTemplate<int> {
public:void foo() {} // 特例化实现
};void func_a() {MyTemplate<int> obj; // 使用特例化版本
}// b.cpp
#include "my_template.h"void func_b() {MyTemplate<int> obj; // 未声明特例化,隐式实例化通用模板
}

编译结果
a.o:包含 MyTemplate<int> 的特例化代码。

b.o:包含 MyTemplate<int> 的通用模板隐式实例化代码。

• 链接时:存在两个 MyTemplate<int> 的定义,导致 链接错误(ODR 违反)。


3. 解决方案:声明特例化
要让所有编译单元使用同一个特例化版本,需遵循以下步骤:// 显式实例化常用类型
// template class MyClassstd::string; // 关键行

(1) 在头文件中声明特例化

// my_template.h
template <typename T>
class MyTemplate { /* 通用实现 */ };// 声明显式特例化(不定义)
template <>
class MyTemplate<int>;

(2) 在源文件中定义特例化

// a.cpp
#include "my_template.h"// 定义特例化
template <>
class MyTemplate<int> { /* 特例化实现 */ };

(3) 其他编译单元直接使用

// b.cpp
#include "my_template.h"void func_b() {MyTemplate<int> obj; // 使用头文件中声明的特例化版本
}

效果:
b.cpp 看到特例化声明后,不会隐式实例化通用模板。

• 链接时仅保留 a.cpp 中的特例化代码,避免重复。


4. 特例化函数的处理
对于函数模板,需使用 extern 声明避免隐式实例化:

(1) 头文件声明

// my_template.h
template <typename T>
void foo(T) { /* 通用实现 */ }// 声明显式特例化
extern template void foo(int);

(2) 源文件定义

// a.cpp
#include "my_template.h"// 定义特例化
template <>
void foo(int) { /* 特例化实现 */ }

(3) 其他编译单元

// b.cpp
#include "my_template.h"void func_b() {foo(42); // 使用 extern 声明的特例化版本
}

5. 关键规则

  1. 特例化必须可见:所有使用特例化模板的编译单元需看到其声明。
  2. ODR 要求:同一模板的显式特例化在整个程序中只能定义一次。
  3. 隐式实例化的触发条件:当未声明特例化时,编译器默认生成通用模板代码。

总结
• 会生成重复代码:若特例化未在头文件中声明,其他编译单元将隐式实例化通用模板。

• 正确做法:

  1. 在头文件中 声明显式特例化(如 extern template class MyTemplate<int>;)。
  2. 在 单个源文件 中定义特例化。
  3. 其他编译单元通过头文件引用特例化版本。

这样可确保所有编译单元使用同一份特例化代码,避免重复定义和链接错误。

http://www.dtcms.com/wzjs/26172.html

相关文章:

  • 邢台网站制作费用济南seo关键词优化方案
  • 公司网站开发制作简单网页制作模板
  • 合肥软件开发seo优化网络推广
  • 2015做导航网站360收录批量查询
  • 庆阳网站设计价格竞价sem托管
  • 做的好的宠物食品网站杭州产品推广服务公司
  • 网页微信版传输助手seo白帽优化
  • 鸿兴网站建设公司上海网络推广服务公司
  • 做外国订单有什么网站别做网络推广员
  • 电子商务毕设做网站沧州seo公司
  • 找网站开发公司seo咨询服务价格
  • 做设计网站的工作内容合肥seo快排扣费
  • 微信公众平台官网登录入口网页版seo项目是什么
  • 咸阳做网站排名c盘优化大师
  • 视频投票网站怎么做的网站网址大全
  • 攻击网站常用方法百度广告运营
  • 做网站宁波大点的网络公司石家庄百度seo
  • 域名出售网站百度客服人工电话24
  • 南沙建设网站拉新推广怎么找渠道
  • 阿里云可以建设多个网站品牌策划包括哪几个方面
  • 摄影网站制作设计泉州全网营销推广
  • 挖掘企业构思的途径百度关键词优化怎么做
  • 做商城网站数据库分类该有哪些5000元做百度推广效果怎么样
  • wordpress注册没有密码seo的优化步骤
  • 宽带动态ip如何做网站访问男生最喜欢的浏览器
  • 拉萨网站制作公司最近爆发什么病毒感染
  • 做韩国外贸网站南宁seo网络优化公司
  • 泰安网站建设有哪些数据分析报告
  • 用户体验设计流程上海seo推广整站
  • pc网站自动生成appseo排名的公司