八、未归类知识点
Author: XFFer_
文章目录
- 八、未归类知识点
01 函数调用运算符、function类模版
1 函数调用运算符
2 map类模版
3 function类模版
函数调用运算符
()
,如果在类中重载了函数调用运算符()
,那么就可以像使用函数一样使用该类的对象了,对象(实参)
。
system("pause");
暂停程序运行,等待任意键继续执行。
class biggerthan
{
public:
int operator()(int getvalue) const
{
if (getvalue < 0)
return 0;
return getvalue;
}
};
biggerthan bgt;
int result = bgt(200);
//int result = bgt.operator()(200);
结论:只要对象所属的类重载了()
“函数调用运算符”,这个类对象就变成可调用对象,并且可以调用多个版本的()
,只要重载()
参数列表有明显差异。
不同调用对象的相同调用形式
调用参数和返回值类型相同,叫做“调用形式”相同。
一种调用形式对应一个函数类型(如int(int)
)。
map模版
map
也是一个类模版/容器,但是不同于vector
,map里每一项是两个数据,一个叫“键”,一个叫“值”。
int func (int value);
#include <map>
map<string, int (*) (int)> func_bag; //map每项有两个数据,这里第一个数据是字符串,第二个数据是int(int)函数类型的指针
func_bag.insert("src", func);
//map<string, function<int (int)> func_bag = {
{"src", func}};
func_bag["src"](3); //func_bag[键]就是map里面的值,也就是函数的入口地址
insert({ , })
用于向map中插入对象。map也有迭代器(回忆:vector的insert功能是用迭代器(指针)向它指向的地址插入对象)
标准库function类型介绍
function也是类模版,要提供模版参数来表示该function类型能够表示的“对象的调用形式”。
#include <functional>
functional<int(int)> f1 = func; //统一调用形式,可以用内部重载()的类对象赋值给f1
02 万能引用universal reference
1 类型区别基本概念
2 universal reference/万能引用/未定义引用 基本认识
3 万能引用资格的剥夺与辨认
universal reference/万能引用/未定义引用 基本认识
万能引用的语境:
- 必须是函数模板
- 必须是发生了模板类型推断并且函数模板形参样子是
T&&
;auto也有万能引用的概念
template <typename T>
void func(T&& src) {
}
int i = 10;
func(i);
func(std::move(i));
万能引用和右值引用解释起来的区别
- 右值引用需要传递右值,否则编译器报错(左值、右值的概念在第2章第12节曾经讲过)
- 万能引用做函数形参时,我们可以传递给它左值,也可以传递给它右值
- 传递左值时,这个万能引用就变成了左值引用
- 传递右值时,这个万能引用就变成了右值引用
template <typename T>
void func(std::vector<T>&& tmp) {
}
这是一个右值引用!!!不是万能引用T&&
是连续的。T可以被其他命名替换。
const
修饰词会剥夺万能引用的资格,而变成右值引用。
03 理解模板类型推断、查看类型推断结果
1 如何查看类型推断结果
2 理解模板类型推断
如何查看类型推断结果
依赖
boost
库
boost库下载链接
需要将下载路径配置到Visual Studio属性管理器的VC++目录的包含目录中。
用boost库返回类型推断结果
#include <boost/type_index.hpp>
template <typename T>
void myfunc(const T& tmprv)
{
using boost::typeindex::type_id_with_cvr;
cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl;
cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>.pretty_name() << endl;
}
理解模板类型推断
- 万能引用
#include <boost/type_index.hpp>
template <typename T>
void myfunc(T&& tmprv)
{
using boost::typeindex::type_id_with_cvr;
cout << "T=" << type_id_with_cvr<T>().pretty_name() << endl;
cout << "tmprv=" << type_id_with_cvr<decltype(tmprv)>.pretty_name() << endl;
}
int i = 10;
myfunc(i); //结果是T= int &, tmprv= int &
myfunc(100); //结果是T= int, tmprv= int &&
//这里包含了引用折叠的知识,会在下一节讲到
- 如果传递的是
const char*const
(第一个const代表指向的对象不能改值,第二个const代表不能改变指向的对象),当传入模板时,返回“T=const char*”“tmprv=const char*”,即可以改变指向的对象,但不可改动该对象的值
04 引用折叠,转发、完美转发,forward
1 引用折叠规则
2 转发、完美转发
3 std::forward
4 std::move和std::forward的区别
hook
template <typename T>
void func(T&& tmprv) {
} //万能引用
int i = 10;
func(i); //借用上一节的boost库判断类型
//这里返回T = int&, tmp = int&
假如我们将推断出的T = int&带入到实例化的模板中
void func(in