C++基础学习第十六课(新特性)

第十六课

C++11/14/17标准
1,强制转换

C语言使用Type b=(Type)a的形式进行强制转换.但是有缺点:万物皆可转,不易区分;

C++提供了四种类型转换操作符用来在不同场合进行强制转换;

类型转换操作符作用
static_cast静态类型转换,编译器做类型检查,基本类型能转换,指针不行;
reinter_cast重新解释类型;
const_cast去掉const属性;
dynamic_cast动态类型转换,运行时检查类型安全,(转换失败返回nullptr),如子类和父类之间的多态类型转换;

1,static_cast 类似C语言的强制转换,进行无条件转换,静态类型转换;

`基本数据类型转换,enum,struct,int,char,float等.static_cast不能进行无关类型(如非基类和子类)指针之间的转换.

`可以用于void*和其他指针类型之间的转换(但是不能用于非void指针之间的转换);

`不能用于两个不相关类型的转换,如:int和int*之间的转换,虽然二者都是四个字节,但他们一个表示数据,一个表示地址,类型不相关,无法进行转换.

int*p=nullptr;
int n=static_cast<int>(p);//error

2,reinterpret_cast 转换的类型必须是一个指针;

`不同类型指针之间的转换;

`int转为指针,指针转为int;

3,const_cast:可以去掉const常量的属性;

const int s=999;
//s=0;//error
int& x=const_cast<int&>(s);
x=80;//true

4,dynamic_cast:动态类型识别,判断父类指向的是哪一个子类对象;

`指针:转换失败返回nullptr;

`引用:转换失败抛std::bad_cast异常;

2,去转义字符

在字符串前加上R,并用()把字符串的数据包括起来;

案例:
char s[]="D:\fssf\dfa";//会发生转义
char d[]=R"(D:\fdf\gfg)";//不会发生转义;
3,decltype类型指导

decltype关键字,和auto的功能相同,都用来在编译时期进行自动类型指导;

decltype是"declare type"的缩写,翻译为"声明类型";
区别:
auto varName=value;
decltype(exp) varMame=value;
//varName 表示变量名,value表示赋给变量的值,exp表示一个表达式;
注意:
auto是根据=右边的初始值value推导出变量的类型,而decltype根据exp表达式推导出变量的类型,跟=右边的value没有关系;因此,auto要求变量必须初始化,而decltype不要求;
exp的注意事项:不能是void;
使用范例:
int n=0;
decltype(n) m=3;//m被推导成了int;
decltype(1.3) u=3.54;//u被推导成了double;
decltype(u+99) f;//f被推导成了double;
4,decltype推导规则

当使用decltype(exp)获取类型时,编译器将根据三条规则得出结果:

1,如果exp是一个不被括号()包围的表达式,那么decltype(exp)的类型就和exp一致;

2,如果exp是函数调用,那么decltype(exp)的类型就和函数返回值的类型一致;

3,如果exp是一个左值,或者被括号()包围,那么decltype(exp)的类型就是exp的引用,假设exp的类型为M,那么decltype(exp)的类型就是M&;

//函数声明
int  fun_int(int);
int* fun_int_ptr(int);
int& fun_int_ref(int);
const int& fun_cint_ref(int);
int main()
{
    int r=999;
    decltype(fun_int(3)) a=r;//a的类型为int;
    decltype(fun_int_ptr) b=&r;//b的类型为int*;
    decltype(fun_int_ref) c=r;//c的类型为int&;
    decltype(fun_cint_ref)(int) d=r;//d的类型为const int&;
    return 0;
}
注意:exp中调用函数时需要带上括号和参数,但仅仅是形式,不会真正的执行函数代码;
5,返回值类型后置
int& foo(int& s)
	{
		return s;
	}
	float foo(float& x)
	{
		return x;
	}
	template<typename T>
	auto fun(T& va)->decltype(foo(va))//使用->就可以返回想要返回的类型,这里是让其自动返回
	{
		reutnr fun(va);
	}
	int main()
	{
		int a = 3;
		float f = 9.4;
		fun(a);
		fun(f);
        return 0;
    }
6,lambda匿名函数
1,定义:
[外部变量访问方式说明符](参数)mutable noexcept -> 返回值类型
{
    函数体;
};
`[外部变量访问方式说明符]:
[]方括号用于向编译器表示当前是一个lambda表达式,其不能省略,在方括号内部,可以注明当前lambda函数的函数体中可以使用哪些外部变量;
外部变量:指的是和当前lambda表达式位于同一作用域的所有局部变量;
`(参数):
和普通函数定义一样,lambda匿名函数也可以接收外部传递的多个参数,和普通函数不同的是,如果不需要传递参数,可以连同()小括号一起省略;
`mutable:
可选,如果使用则之前的()小括号不能省略(参数个数可以为0),默认情况下,对于以值传递方式引入的外部变量,不允许在lambda表达式内部修改它们的值(可以理解为这部分变量都是const常量),而如果想要修改它们,就必须使用mutable关键字;
`noexcept:
可选,如果使用,在之前的()小括号将不能省略(参数个数可以为0),默认情况下,lambda函数的函数体中可以抛出任何类型的异常,而标注noexcept关键字,则表示函数体内不会抛出任何异常;
案例1:
    //= 以值的方式捕获,而且在函数的内部不可以修改变量的值,自动加了const;
	//可以在后面加上mutable,可以在函数内部修改外部变量,但外部变量的值不变;
	int a = 4;
    auto fun=[=]() mutable
	{
		a=11;
		cout << a << endl;
	};
	fun(); //11
	cout << a;//4
案例2:
    //& 以引用的方式捕获,可以修改外部变量的值,而且会改变外部变量的值;
    int a = 4;
	auto fun = [&]()
	{
		a = 99;
		cout << a << endl;
	};
	fun();//99
	cout << a;//99
7,完美转发

template

C++引入模板函数forward(),调用该函数可以将函数模板接收到的形参连同其右,左属性一起传递给被调用的函数;

案例:
void otherfun(int& a)
{
	cout << "左值引用" << endl;
}
void otherfun(const int& a)
{
	cout << "const 引用" << endl;
}
template<typename T>
auto fun(T&& bal) 
{
	otherfun(std::forward<T>(bal));
}
//auto fun(T bal) 
//{
//	otherfun(bal);
//}
int main()
{
	int f = 9;
	int& a = f;
	fun(f);//左值引用
	fun(23);//const引用//不使用forward会调用左值引用
	return 0;
}
注意:
1,当实参为左值或者左值引用(A&)时,函数模板中T&&转变为A&(A& && =A&);
1,当实参为右值或者右值引用(A&&)时,函数模板中T&&将转变为A&&(A&& &&=A&&);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值