《C++ Primer Plus》读书笔记 第8章 函数探幽

第8章 函数探幽

1.内联函数

对于内联函数,编译器将使用相应的函数代码替换函数调用。对于内联代码,程序无需跳到另一个位置处执行代码,再跳回来。因此,内联函数的运行速度比常规函数稍快,但代价是需要占用更多内存。

要使用内联函数,必须在函数声明或函数定义前加上关键字inline,且该函数不能过大或有递归:

inline void print()
{
cout << “Hello World!<< endl;
}

2.临时变量、引用参数和const

当函数的形参中有引用时,如果实参与引用参数不匹配,C++将生成临时变量。如果引用参数是const,则编译器将在下面两种情况下生成临时变量:

  • 实参的类型正确,但不是左值(可以通过地址访问的值)。
  • 实参的类型不正确,但可以转换为正确的类型。

应尽量将引用参数声明为const数据,因为:

  • 使用const可以避免无意中修改数据的编程错误。
  • 使用const使函数能够处理const和非const实参,否则只能接受非const数据。
  • 使用const引用使函数能够正确生成并使用临时变量。

3.函数返回引用的优点

在下面的语句中:

dup = accumulate(team, five);

如果accumulate()返回一个结构,而不是指向结构的引用,将把整个结构复制到一个临时位置,再将这个拷贝复制给dup。但在返回值为引用时,将直接把team复制到dup,其效率更高。

返回引用的函数实际上是被引用的变量的别名。

4.默认参数

对于带参数列表的函数,必须从右向左添加默认值。也就是说,要为某个参数设置默认值,则必须为它右边的所有参数提供默认值:

int harpo(int n, int m = 4, int j = 5);	//VALID
int chico(int n, int m = 6, int j);		//INVALID
int groucho(int  k = 1, int m = 2, int n = 3);	//VALID

5.函数模板

函数模板的定义:

template <typename AnyType>
void Swap(AnyType &a, AnyType &b)
{
	AnyType temp;
	temp = a;
	a = b;
	b = temp;
}

其中typename也可以是class。

函数模板也可以进行重载。

6.隐式实例化、显式实例化、显式具体化

如果希望一个函数模板为某一种特定的类型执行不同的操作,则可以使用显式具体化

编译器使用模板为特定类型生成函数定义时,得到的是模板实例。这种实例化的方式被称为隐式实例化。也可以直接命令编译器创建特定的实例,这种实例化的方式称为显式实例化

隐式实例化、显式实例化和显式具体化统称为具体化。它们的相同之处在于,它们表示的都是使用具体类型的函数定义,而不是通用描述。

template <typename T>
void Swap (T &, T &);	//模板原型

template <> void Swap<job> (job &, job &);	//显示具体化
int main()
{
	template void Swap<char>(char &, char &);		//显式实例化
	short a, b;
	...
	Swap(a, b);	//为short类型隐式实例化
	job n, m;
	...
	Swap(n, m);	//使用显式具体化的模板
	char g, h;
	...
	Swap(g, h);	//使用显式实例化的模板
	...
}

编译器看到char的显式实例化后,将使用模板定义来生成Swap()的char版本。对于其他的Swap()调用,编译器根据函数调用中实际使用的参数,生成相应的版本。当编译器看到Swap(n, m)后,将使用为job类型提供的独立定义(显示具体化)。当编译器看到Swap(g, h)后,将使用处理显式实例化时生成的模板具体化。

7.关键字decltype

编写模板函数时,一个问题是并非总能知道应在声明中使用哪种类型:

template<typename T1, typename T2>
void ft(T1 x, T2 y)
{
	...
	?type? xpy = x + y;
	...
}

xpy应为什么类型呢?由于不知道ft()将如何使用,因此无法预先知道这一点。这时就可以利用关键字decltype:

template<typename T1, typename T2>
void ft(T1 x, T2 y)
{
	...
	decltype(x + y) xpy = x + y;
	...
}

decltype()的括号中如果是一个函数调用,实际上并不会调用函数,编译器通过查看函数的原型来获悉返回类型,而无需实际调用函数。

8.后置返回类型

有一个相关的问题是decltype本身无法解决的:

template<typename T1, typename T2>
?type? gt(T1 x, T2 y)
{
	...
	return x + y;
}

由于无法预先知道将x和y相加得到的类型。好像可以将返回类型设置为decltype(x + y),但此时还未声明参数x和y,它们不在作用域内。为此,C++新增了一种声明和定义函数的语法:

template<typename T1, typename T2>
auto gt(T1 x, T2 y) -> decltype(x + y)
{
	...
	return x + y;
}

这将返回类型移动到了参数声明的后面。->decltype被称为后置返回类型,decltype也可以改为其他任意的类型。其中auto是一个占位符,表示后置返回类型提供的类型,这是C++11给auto新增的一种角色。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值