《C++ Primer Plus(第六版)》(10)(第八章 函数探幽 笔记)
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; }; } #endifcpp文件:
#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);在函数里面再确定返回的类型。
最后,对于函数模板,很多时候都是在使用而已,而且不知不觉中,毕业这么久都没有自己写过模板。
书中那么复杂的函数匹配,对一般人来说,真的没什么用,出现两三个重载函数,都已经觉得蛋疼了,里面还写了那么多。
或者后面接触模板库的时候,会很重要的吧