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。
C++ Templates (1.6 但是为什么不...? But, Should't We ...?)的更多相关文章
- 解决Windows版Git出现templates not found的问题
环境: Win10 x64 Git windows客户端(下载自 https://git-scm.com/) SourceTree 1.9.6.1(使用系统安装的Git,而非SourceTree内嵌的 ...
- [c++] Templates
Template是编译时多态.所有的模板都是在编译时产生对应的代码,它没有面向对象中的虚表,无法实现动态多态. Function Template A function template is a p ...
- webstrom live templates
javascript: 在live templates底部要选择javascript # $('#$END$') $ $($end$) $bd $(document.body) $d $(docume ...
- Myeclipse Templates详解(一) —— Java模板基础
目录 Templates简介 MyEclipse自带Templates详解 新建Template 自定义Template 因为自己比较懒,尤其是对敲重复代码比较厌恶,所以经常喜欢用快捷键和模板,Mye ...
- Using FreeMarker templates (FTL)- Tutorial
Lars Vogel, (c) 2012, 2016 vogella GmbHVersion 1.4,06.10.2016 Table of Contents 1. Introduction to F ...
- juqery模板 Templates
现在已经有了许多JavaScript的解决方案模板,从这方面说,标准化的模板解决方案必然是大势所趋.在本节中,我们向你简要描述四个最流行最有趣的模板.现有的模板解决方案能解决什么?那些特色在jQuer ...
- django TEMPLATES
?: (1_8.W001) The standalone TEMPLATE_* settings were deprecated in Django 1.8 and the TEMPLATES dic ...
- django复习笔记3:urls/views/templates三板斧
0.先看看文件结构 mysite/ mysite/ ├── __pycache__ │ └── manage.cpython-.pyc ├── blog │ ├── __init__.py │ ...
- Effective C++ -----条款44:将与参数无关的代码抽离templates
Templates生成多个classes和多个函数,所以任何template代码都不该与某个造成膨胀的template参数产生相依关系. 因非类型模板参数(non-type template para ...
- 第三节:视图(Views)和模板(Templates)
目录 概览 编写视图 编辑视图实际做一些事情 抛出404异常 使用模板系统 移除在代码中的硬编码网址 Url名称的命名空间 概览 视图是Django应用的网页的“类型”,一般服务于特定的功能并且有特定 ...
随机推荐
- docker时区不正确的问题修改记
前一阵子有一台服务器,mysql的时间比北京时间晚了8个小时.我知道是时区的问题,但是不知道为什么弄成这样,宿主机没有问题,后来一看mysql的docker,时区是错的. mybatis-plus打印 ...
- laravel报错1071 Specified key was too long; max key length is 1000 bytes
Laravel 默认使用utf8mb4字符编码,而不是的utf8编码.因此运行php artisan migrate会出现如下错误: [Illuminate\Database\QueryExcepti ...
- Spring+hibernate+JSP实现Piano的数据库操作---2.Controller+Service+Dao
Controller package com.controller; import com.entity.Piano; import org.dom4j.rule.Mode; import org.s ...
- link小图标以及表格的用法基础
一.网页小图标的实现 实例: 实现方式: 效果: 二.表格基础 1.表格的组合标签 常用: table tr td caption ①table属性 border 边框 width 宽度 默认按照 ...
- cmd 安装第三方库问题
pip install 包名 -i http://pypi.douban.com/simple/ --trusted-host pypi.douban.com 一定要指定 信任豆瓣源,不然就算换了源 ...
- Python列表函数和方法
Python列表函数和方法: 函数: len(列表名): 返回列表长度 # len(列表名): # 返回列表长度 lst = [1,2,3,'a','b','c'] print("lst 列 ...
- 4.18 省选模拟赛 无聊的计算器 CRT EXBSGS EXLucas
算是一道很毒瘤的题目 考试的时候码+调了3h才搞定. op==1 显然是快速幂. op==2 有些点可以使用BSGS 不过后面的点是EXBSGS. 这个以前学过了 考试的时候还是懵逼.(当时还是看着花 ...
- Linux 如何以管理员身份运行终端
如何以管理员身份在终端执行指令: 目录 如何以管理员身份在终端执行指令: 1. 以sudo 指令在其他指令前加上sudo 2. 以su 进入root权限,以管理员方式执行命令 设置root初始密码: ...
- 数据库Schema
在学习SQL的过程中,会遇到一个让你迷糊的Schema的概念.实际上,schema就是数据库对象的集合,这个集合包含了各种对象如:表.视图.存储过程.索引等.为了区分不同的集合,就需要给不同的集合起不 ...
- CSP-J 2019游记
准备篇 11.16早上,在南校集合后,大巴车开往日照. 在车上颓了一上午 中午到达日照,考场在山东外国语技术大学(SWUV) 到了大学里的餐厅潦草的吃完饭后去学术报告厅继续颓废 一到山外突然想起了暑假 ...