您的位置:首页 > 编程语言 > C语言/C++

《C++ Primer Plus(第六版)》(10)(第八章 函数探幽 笔记)

2016-12-14 00:02 417 查看
1.内联函数比普通的函数稍快,但是要用更多的内存,每一个对象都有一个函数副本。

2.内联函数并不是声明了,最终就是内联的。编译器会自己筛选,例如代码过长,递归,都会被过滤掉。甚至编译器可能没有或者实现这种特性。

3.内联函数可以写到cpp文件里面的。一直都误会了只能写到头文件,搞到这么乱。

头文件:

#ifndef _CppServer_Test_TestManager_H_
#define _CppServer_Test_TestManager_H_
#include <set>
#include <string>

using namespace std;
namespace CppServer
{
class CTestManager
{
public:
inline int getA();
private:
int _a;
};
}
#endif
cpp文件:

#include "Test/TestManager.h"
using namespace CppServer;
inline int CppServer::CTestManager::getA()
{
return _a;
}
好吧。再研究一下,说要在调用的地方,可以看到函数的实现才行,否则会链接失败。

另外,也不是每个编译器都支持的,而且就算编译器支持了,生成的obj文件,lib文件,dll文件,各种格式,可能也会有些地方会不支持。

网上大家的建议是:不要过多关注内联函数,让编译器去选择就行。

4.左值:

左值参数是可被引用的数据对象,例如:变量、数组元素、结构成员、引用和解除引用的指针都是左值。

非左值包括字面常量(用引号括起的字符串除外,他们由其它地址表示)和包含多项的表达式。

5.右值引用,相对于左值来说的,使用&&可以进行右值引用。又是C++11的东西。

int&& a = 121;

6.模板函数

显示具体化(explicit specialization)

相同的函数名,可以有非模板函数、模板函数和显示具体模板函数以及他们的重载版本

显示具体化的原型和定义应以template<>开头,并通过名称支出类型

具体化优先于常规模板,而非模板函数优先于具体化和常规模板

#include <iostream>
#include <set>
using namespace std;

struct job
{
char name[40];
double salary;
int floor;
};
//常规模板函数
template <typename T> void change(T& a, T& b)
{
T temp = a;
a = b;
b = temp;
}
//具体化的模板函数
template<> void change<job>(job& j1, job& j2)
{
change(j1.salary, j2.salary);
change(j1.floor, j2.floor);
}
//普通函数
void show(job& j)
{
cout << j.name << ": $" << j.salary << " on floor " << j.floor << endl;
}
int main()
{
int a = 10;
int b = 20;
cout << a << '\t' << b << endl;
change(a, b);//隐式模板实例
cout << a << '\t' << b << endl;

job sue = { "susan yaffee", 73000.60, 7 };
job sidney = { "sidney taffee", 2332, 9 };
show(sue);
show(sidney);
change(sue, sidney);//调用具体化的模板函数
show(sue);
show(sidney);

return 0;
}
代码中包含了模板函数的时候,并没有生成真正的函数。模板函数,只是一个生成函数的方案。

实例化(instantiation)

隐式实例化(implicit instantiation)

只有代码中调用了,编译器才使用模板生成函数的实例,这种叫做隐式实例化,例如上面的change(a,b);

显式实例化(explicit instantiation)

template void change<int>(int, int);


实现了显式实例化的编译器,看到这个后,就会生成一个int类型的实例。例如上面调用模板函数的时候这样写
change<double>(a,b);

我这样改了之后,就是显式实例化了,但是这样会报错,因为传入的是int,是不能使用double&的
error C2664: “void change<double>(T &,T &)”: 无法将参数 1 从“int”转换为“double &”
还可以这样使用:
template void change<char>(char&, char&);//先声明,生成了char的函数
char c = 'a';
char d = 'b';
change(c, d);//这里直接使用了,没有进行生成

不知道为什么书上的代码是写在main函数里面,我这里写在main函数里面是报错的。

再对照一下,显式具体化的声明。
template<> void change<int>(int&, int&);
template<> void change(int&, int&);

在同一个文件中,使用同一种类型的显式实例化和显式具体化是会出错的。

隐式实例化,显式实例化,显式具体化,统称为具体化(specialization)
这个书上说的不是很详细,其实我甚至不知道显式实例化究竟有什么用的。

7.模板函数内可以使用特定的表达式来确定类型
decltype(expression) var

8.后置返回类型
在函数模板中,可能不确定返回的类型是什么,这个时候可以使用后置返回类型,例如:

auto fun(int, int);
在函数里面再确定返回的类型。

最后,对于函数模板,很多时候都是在使用而已,而且不知不觉中,毕业这么久都没有自己写过模板。

书中那么复杂的函数匹配,对一般人来说,真的没什么用,出现两三个重载函数,都已经觉得蛋疼了,里面还写了那么多。
或者后面接触模板库的时候,会很重要的吧








                                            
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息