C++ Templates (1.6 但是为什么不...? But, Should't We ...?)
1.6 但是为什么不...? But, Should't We ...?
可能,甚至简单的函数模板可能引发进一步的疑问,这些疑问可能如此常见,所以在此简单地进行讨论。
1.6.1 传值还是传引用? Pass by Value or by Reference?
读者可能疑惑,为什么截止目前为止声明的函数使用传值方式而非传引用方式传递参数。除了一些拷贝代价小的简单类型(如基本类型(fundamental types)或者std::string_view),通常推荐以引用方式进行参数传递,因为没有非必要拷贝被创建。
然而,由于一些原因,值传递方式通常更好:
语法更简单
编译器更好优化
移动语义(move semantics)使得拷贝成本更低
有时根本没有拷贝或者移动问题
此外,对于模板来说会掺杂一些特殊的方面:
模板可被用于简单和复杂的类型,所以选择适用于复杂类型的方式可能导致简单类型效率低下(counter-productive)
调用者依然可以决定使用值传递还是引用传递,通过使用
std::ref()
和std::cref()
,详见第7.3节尽管对于传递字符串字面值(string literal)或者裸数组(raw arrays)总是问题,以引用方式传递他们通常会导致更大的问题。
这些都将在第7章中进行详细讨论。此刻,在本书中通常使用传值方式进行参数传递,除非一些功能只能使用引用。
1.6.2 为什么不使用inline? Why Not inline?
通常,函数模板不需要声明为inline。与普通非inline函数不同,非inline函数模板可以定义在头文件中,并且可以在多个解释单元(translate units)包含此头文件。
该规则的唯一例外是模板针对某些类型的全特化(full specialization),因此得到的代码不再是泛型(generic)的(所有的模板参数均已定义)。更多细节参考9.2节。
从一个严格的语言定义角度来看,inline仅仅意味着一个函数的定义可以在一个程序中出现多次。然而,这也意味着给编译器一个提示:对该函数的调用应当内联地展开(expanded inline)。在某些情形下,如此做可以产生更高效的代码,但是在其他情形下却完全相反。当今,在没有指定inline的情形下,编译器通常能更好地决定是否内联展开。然而,在该决策过程中,编译器依然对出现inline的情形负责(compilers still account for the presence of inline in that decision)。
1.6.3 为什么不使用constexpr? Why Not constexpr?
自从C++11起,可以使用constexpr来提供在编译期使用代码计算值的能力。对许多模板来说,这非常有意义。
比如,为了在编译期能够计算最大值函数,可以这样声明:
// basics/maxconstexpr.hpp
template<typename T1, typename T2>
constexpr auto max(T1 a, T2 b)
{
return b < a ? a : b;
}
该模板函数可以被用于需要编译期计算的地方,比如当声明裸数组的大小:
int a[::max(sizeof(char), 1000u)];
或者声明std::array<>的大小:
std::array<std::string, ::max(sizeof(char), 1000u)> arr;
此处,1000作为unsigned int
来避免在模板中“比较有符号和无符号数比较”的警告。
第8.2节将讨论使用constexpr的其他例子。然而,为了将注意力放在基本问题上,当讨论其他模板特性时,通常会跳过constexpr。
最新文章
- $Host.Runspace.ThreadOptions = “ReuseThread”有神马用?
- 【POI】使用POI处理xlsx的cell中的超链接 和 插入图片 和 设置打印区域
- mysql部署到云主机的笔记
- PHP中$_REQUEST中包含的数据,数据被覆盖问题
- 【windows开发实现记事本程序&mdash;&mdash;逻辑篇1】
- Oracle sql语言模糊查询--like后面的通配符
- xpage 获取 附件
- RH133读书 笔记(3) - Lab 3 Configuring the kernel
- DOM编程从入门到忘记
- 树的常见算法&;图的DFS和BFS
- AngularJS进阶(八)实现页面跳转并进行参数传递
- C# 比较两文本相似度
- com.android.support:design
- 内存映射函数remap_pfn_range学习——示例分析(2)
- spring中 context:property-placeholder 导入多个独立的 .properties配置文件
- C++(指针和高级指针)-上篇
- Windows文件共享,报错";该用户已禁用";解决方案
- karma
- [poj3159]Candies(差分约束+链式前向星dijkstra模板)
- Linux errno错误对照表
热门文章
- GhostNet: More Features from Cheap Operations
- 还不懂mysql的undo log和mvcc?算我输!
- MacOS下SpringBoot基础学习
- PHP date_timezone_get() 函数
- PHP tmpfile() 函数
- PHP log1p() 函数
- C#后台实现在Grid标签中动态新增CheckBox标签(WPF中)
- ElasticSearch 基础入门 and 操作索引 and 操作文档
- P3250 [HNOI2016]网络
- 【JSOI2007】文本生成器 题解(AC自动机+动态规划)