目录
类型转换
C语言风格的类型转换符
(type)expression
type(expression)
C++中有4个类型转换符
static_cast
dynamic_cast
reinterpret_cast
const_cast
使用格式:xx_cast
class Person{
public:
int m_age;
virtual void run(){
cout<<"Person::run()"<<endl;
}
};
class Student:public Person{
};
class Car{};
//const_cast作用
//一般用于去除const属性,将const转换成非const
void const_cast_using(){
const Person * p1 = new Person();
//p1->m_age = 10;//不可以改变p1指向的内存空间的值
//C语言的强制类型转换
Person * p2 = (Person*)p1;
p2->m_age = 20;
cout<<"p1->m_age is "<<p1->m_age<<endl;
//C++的强制类型转换
Person * p3 = const_cast<Person*>(p1);
p3->m_age = 30;
cout<<"p1->m_age is "<<p1->m_age<<endl;
}
//dynamic_cast作用
//一般用于多态类型的转换,有运行时安全检测
void dynamic_cast_using(){
Person * p = new Person();
Student * s = new Student();
cout<<"p is "<<p<<endl;//p is 0x100653180
cout<<"s is "<<s<<endl;//s is 0x1006535a0
//父类指针是可以指向子类对象的
Person *p2 = s;
//但子类指针指向父类对象时是不安全的。因为子类指针访问的内存空间明显要大于父类指针
//C类型的强制转换
Student * s2 = (Student*)p;//没有安全监测直接赋值
cout<<"s2 is "<<s2<<endl;//s2 is 0x100653180
//C++类型的强制转换
Student * s3 = dynamic_cast<Student*>(p);//有运行时安全检测
cout<<"s3 is "<<s3<<endl;//s3 is 0x0
//可以交叉转换
Car * car = dynamic_cast<Car*>(p);
cout<<"car is "<<car<<endl;//car is 0x0
}
//static_cast作用
/**
对比dynamic_cast,缺乏运行时安全检测
不能交叉转换(不是同一继承体系的,无法转换)
常用于基本数据类型的转换、非const转成const
适用范围较广
*/
void static_cast_using(){
Person * p1 = new Person();
cout<<"p1 is "<<p1<<endl;//p1 is 0x1007a8b20
//没有运行时安全监测
Student * stu1 = static_cast<Student*>(p1);
cout<<"stu1 is "<<stu1<<endl;//stu1 is 0x1007a8b20
//不能交叉转换
//Car * car = static_cast<Student*>(p1);
}
//reinterpret_cast作用
/**
属于比较底层的强制转换,没有任何类型检查和格式转换,仅仅是简单的二进制数据拷贝
可以交叉转换
可以将指针和整数互相转换
*/
void reinterpret_cast_using(){
//将100直接放到变量p的内存空间内
long * p = reinterpret_cast<long*>(100);
cout<<"p is "<<p<<endl;
//将地址转为数字放到变量num内
long num = reinterpret_cast<long>(p);
cout<<"num is "<<num<<endl;
//
int i1 = 10;
double d1 = reinterpret_cast<double &>(i1);
cout<<"d1 is "<<d1<<endl;
//
int i2 = 10;
double d2 = (double)i2;
cout<<"d2 is "<<d2<<endl;
}
C++11
一、auto
auto的使用
可以从初始化表达式中推断出变量的类型,大大简化编程工作
属于编译器特性,不影响最终的机器码质量,不影响运行效率
void autoUsing(){
auto i = 10;//int
auto str = "c++";//const char *
auto p = new Person();//Person*
p->run();
}
二、decltype
可以获取变量的类型
void decltype_using(){
int a = 10;
decltype(a) b = 20;//int
typeof(a) c = 30;//int
}
三、nullptr
可以解决NULL的二义性问题
如果是空指针使用 nullptr
void funcTest(int v){
cout<<"funcTest(int v)"<<endl;
}
void funcTest(int *v){
cout<<"funcTest(int *v)"<<endl;
}
void nullptr_using(){
//funcTest(NULL);//Call to 'funcTest' is ambiguous
funcTest(0);
funcTest(nullptr);
}
四、快速遍历
void fast_bianli(){
int array[] = {11,22,33,44};
for (int item : array) {
cout<<"item is "<<item<<endl;
}
//更加简洁的初始化
int array2[]{11,22,33,44};
int a{10};
cout<<"a is "<<a<<endl;
int b(20);
cout<<"b is "<<b<<endl;
}
五、lambda表达式
/**
◼ Lambda表达式
有点类似于JavaScript中的闭包、iOS中的Block,本质就是函数
完整结构: [capture list] (params list) mutable exception-> return type { function body }
✓capture list:捕获外部变量列表
✓params list:形参列表,不能使用默认参数,不能省略参数名
✓ mutable:用来说用是否可以修改捕获的变量
✓ exception:异常设定
✓return type:返回值类型
✓function body:函数体
有时可以省略部分结构
✓[capture list] (params list) -> return type {function body}
✓[capture list] (params list) {function body}
✓[capture list] {function body}
*/
//1、C++11新特性:lambda表达式
void lambdaUsing(){
//函数指针 p 指向一个函数地址 返回值是int,有两个参数 int int
int(*p)(int,int);
//lambda表达式的本质是函数
int (*p1)(int ,int ) = [](int a,int b)->int{
return a + b;
};
int c = p1(1,2);
cout<<"c is "<<c<<endl;
//直接调用
int c1 = ([](int a1,int b1)->int{
return a1+b1;
})(2,3);
cout<<"c1 is "<<c1<<endl;
//参数和返回值可以省略
int (*p2)(void) = []{
return 100;
};
int c2 = p2();
cout<<"c2 is "<<c2<<endl;
}
//lambda表达式作为函数参数
int exec(int a,int b,int(*func)(int ,int)){
return func(a,b);
}
void lambdaUsing2(){
cout<<exec(20, 10, [](int a,int b)->int{return a+b;})<<endl;
cout<<exec(20, 10, [](int a,int b)->int{return a-b;})<<endl;
cout<<exec(20, 10, [](int a,int b)->int{return a*b;})<<endl;
cout<<exec(20, 10, [](int a,int b)->int{return a/b;})<<endl;
}
//2、变量捕获
void lambdaCatch(){
int a = 10;
int b = 20;
//值捕获
auto func = [a,b]{
//a++;//无法访问变量a,也不存在局部变量a
cout<<"a is "<<a<<endl;
cout<<"b is "<<b<<endl;
};
//值捕获(=表示隐式捕获)
auto func2 = [=]{
cout<<"a is "<<a<<endl;
cout<<"b is "<<b<<endl;
};
//a是值捕获,其余变量是地址捕获
auto func3 = [&,a]{
cout<<"a is "<<a<<endl;
cout<<"b is "<<b<<endl;
};
//a是地址捕获,b是值捕获
auto func4 = [&a,b]{
//a++;//访问的外部变量a,因为是地址传递
cout<<"a is "<<a<<endl;
cout<<"b is "<<b<<endl;
};
//隐式捕获(地址捕获)
auto func5 = [&]{
cout<<"a is "<<a<<endl;
cout<<"b is "<<b<<endl;
};
//a是地址捕获,其余变量是值捕获
auto func6 = [=,&a]{
cout<<"a is "<<a<<endl;
cout<<"b is "<<b<<endl;
};
a++;
b++;
func();
cout<<"------1-----"<<endl;
func2();
cout<<"------2-----"<<endl;
func3();
cout<<"------3-----"<<endl;
func4();
cout<<"------4-----"<<endl;
func5();
cout<<"------5-----"<<endl;
func6();
cout<<"------6-----"<<endl;
}
//3、mutable
void mutableUsing(){
int a = 10;
auto func = [a]() mutable{
cout<<"++a is "<<++a<<endl;
};
//mutable的作用如下代码所示
// auto func1 = [a](){
// int b = a;
// cout<<"++a is "<<++b<<endl;
// };
func();
cout<<"a is "<<a<<endl;
}
C++14
//泛型lambda表达式
void fanxingLambda(){
auto func = [](auto v1,auto v2){
return v1 + v2;
};
cout<<func(10,20.5)<<endl;
}
//对捕获的变量进行初始化
void initCatchVar(){
int a ;
auto func = [a = 10]{
cout<<a<<endl;
};
func();
//这里仍是未初始化的变量a
cout<<a<<endl;
}
C++17
//可以进行初始化的if、switch语句
void initIfAndSwich(){
//变量a、b的作用域是它所在的if语句,以及其后面的if-else语句
if (int a = 10;a>10) {
a = 1;
}else if(int b = 20;a>b && b>10){
b = 2;
a = 2;
}else{
a = 3;
b = 4;
}
//变量a的作用域是它所在swich语句
switch (int a = 10;a) {
case 1:
break;
case 5:
break;
case 10:
break;
default:
break;
}
}
行者常至,为者常成!