【C++】十二、explicit,volatile,mutable关键字和模板- - - -函数模板

本文深入探讨了C++中的explicit关键字,用于禁止隐式类型转换,volatile用于禁止编译器优化并确保多线程安全性,以及mutable关键字,允许修改常量对象的特定成员。此外,详细介绍了函数模板的基本概念,包括函数模板的实例化、参数演绎、特例化、类型参数和非类型参数,以及函数模板的默认值、重载、显式实例化等关键点。
摘要由CSDN通过智能技术生成

【一】explicit、volatile、mutable关键字

【1. explicit:】

禁止隐式生成临时对象;在内置类型转换为自定义类型进行赋值时,当没有明确指出对象时,会隐式产生临时对象,这个是编译器推演产生的那么就存在不可控因素,假如我们不想它转换,但是它还是转换了,那么就有安全隐患的存在。

将其加在构造函数前面,可以禁止隐式生成临时对象

【2. volatile:】

禁止编译器优化。

编译器可能会对多个文件进行代码顺序调正,那么在多线程的情况下,代码顺序变了,结果就不一样了,是一种不可控的因素。所以可以用此关键字修饰,禁止编译器优化。

【3. mutable:】

去除常量的常性。

可以修改常量,如下面,test为常对象,不允许修改其成员变量,但是我现在必须要修改ma,那么就可以去除ma的常性,让其可以被修改。在智能指针时会用到。

class Test
{
private:
	    mutable int ma;//去除常性
	    int mb;
};
int main()
{
	const Test test(10,20);
	test.ma=100;//必须要修改ma,加上mutable就可以修改了
}

【二】函数模板

一、函数模板基本概念

(一)基本概念

想要写出一个可以适用于任何类型的函数,C用宏或泛型处理,但都有缺陷,前面我们说C++可以适用重载实现,但是当类型很多时,代码冗余度过高,不建议适用。C++还提供了另外一种方式,模板。基本概念有:

【1. 模板函数】

含有模板类型参数的泛化函数,不可以直接使用。

  • 在定义点,只编译模板的头部,告诉编译器,这是一个函数模板,在调用点编译模板实例化后的模板函数。所以模板体在整个过程中不处理,函数模板中有错误时,只要不实例化为函数模板调用就不会报错。
  • 格式:
    template<typename T,……> //关键字<模板类型参数,……>
    void Test(T a)//函数模板
    

【2. 模板的实例化】

在主函数中,利用

Test<int>(10)//函数名<类型>(参数列表)

对函数进行实例化。即调用点通过具体类型替换模板列表参数的过程

【3. 函数模板】

将模板函数实例化后的函数,此时的函数已经拿实例化的类型替换了模板类型参数,生成了一份代码,在程序运行,编译模板函数。

用一张图表示三者的关系

在这里插入图片描述
注意:

  • 根据是否上方紧跟着template关键字来判断是否为一个模板,存在就是模板。
  • 函数模板是一个壳子,不编译实体部分
  • 模板函数是用函数模板刻画出来的产物,所以逻辑语法必须和函数模板一致

(二)实现两个数求和函数模板

我们看一个具体的例子

/*1.两个数求和*/
template <typename T1,typename T2>
T1 TwoSum(T1 num1,T2 num2)
{
   
	return num1+num2;
}
int main()
{
   
	std::cout<<TwoSum<int,int>(1,2)<<std::endl;
}

可以处理任意两个类型的数值相加,如int,double等。我们通过这个函数看一下函数模板,模板函数,模板的实例化这三个概念:
在这里插入图片描述

二、函数模板的参数演绎

当实例化函数模板时,会用对应的类型替换模板类型参数,那么这个替换的过程,是简单的文本替换#define,还是类型重定义typedef呢,如TwoSum<int,int>(10,20)用int替换T是怎么的呢?

模板的处理,在编译阶段,那么就是在编译阶段进行类型重定义得到模板参数。就是做了typedef int T 。在调用点设计者传入类型进行模板实例化,具体类型会替换T,生成模板函数。

现在尝试这样的调用:TwoSum(10,20)在调用点设计者没有给出类型,但是程序却调用成功,表示生成了模板函数,存在具体类型替换T的过程,原因是:系统通过实参推演给出了具体类型,这就是模板的实参推演。

模板的实参推演:调用点没有给出类型的情况下,由系统通过实参推演出来我们需要的类型。

可以这样理解:模板头部已经编译了,这时编译器知道模板头部需要的是两个相同的类型,然后根据实参10,20是两个相同类型的整型int,由此推演出来模板实例化用整型int来替换,生成了一份int类型的模板函数

模板的实参推演需要注意:

  • 不能让编译器产生二义性。 如函数模板的头部需要两个同一类型的参数,但是调用点传入10,10.1数值,那么编译器就会推演出int,double两种类型,这时它不知道应该拿那个类型去实例化,这就让它产生了二义性,它就报错。
  • 一趟调用过程中,一个模板类型参数只能用一个类型来替换
  • 存在实参时,才可以进行模板实参的推演。

三、函数模板的特例化

我们现在尝试写一个比较大小的函数模板:

/*3.比较大小*/
template <
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值