类型转换
- C语言类型转换:
- (type)expression
- expression(type)
#include <iostream>
using namespace::std;
int main(int argc, const char * argv[]) {
int a = 10;
double d1 = (double)a;
double d2 = double(a);
return 0;
}
- C++语言类型转换:
- xx_cast<type>(expression)
const_cast
- 一般用于去除const属性,将const转成非const;
#include <iostream>
using namespace::std;
class Person {
public:
int m_age;
};
int main(int argc, const char * argv[]) {
//不可修改
const Person *p1 = new Person();
//const_cast 变成可修改
Person *p2 = const_cast<Person *>(p1);
p2->m_age = 20;
return 0;
}
dynamic_cast
- 一般用于多态类型的转换,有运行时安全检测;
#include <iostream>
using namespace::std;
class Person {
public:
int m_age;
virtual void run(){};
};
class Student : public Person{
public:
int m_score;
};
int main(int argc, const char * argv[]) {
Person *p1 = new Person();
Person *p2 = new Student();
Student *s1 = dynamic_cast<Student *>(p1);//不安全的 无值NULL
Student *s2 = dynamic_cast<Student *>(p2);//安全的 有值
return 0;
}
static_cast
- 对比dynamic_cast,缺乏运行时安全检测;
- 不能交叉转换,即类型完全不同的;
- 常用于基本数据类型转换,非const转成const;
- 使用范围广泛;
#include <iostream>
using namespace::std;
class Person {
public:
int m_age;
virtual void run(){};
};
class Student : public Person{
public:
int m_score;
};
class Car {
public:
};
int main(int argc, const char * argv[]) {
Person *p1 = new Person();
Person *p2 = new Student();
Student *s1 = static_cast<Student *>(p1);//不安全 有值
Student *s2 = static_cast<Student *>(p2);//安全 有值
Car *c1 = static_cast<Car *>(p1); //报错 不能转换 类型不同
int i = 10;
double d = static_cast<double>(i);
return 0;
}
reinterpret_cast
- 属于比较底层的强制类型转换,没有任何类型检查和格式转换,仅仅是简单的二进制数据的拷贝;
- 可交叉转换;
#include <iostream>
using namespace::std;
class Person {
public:
int m_age;
virtual void run(){};
};
class Student : public Person{
public:
int m_score;
};
class Car {
public:
};
int main(int argc, const char * argv[]) {
Person *p1 = new Person();
Person *p2 = new Student();
Student *s1 = reinterpret_cast<Student *>(p1);//不安全 有值
Student *s2 = reinterpret_cast<Student *>(p2);//安全 有值
Car *c1 = reinterpret_cast<Car *>(p1); //不报错 能转换 类型不同 有值
int i = 10;
double d = reinterpret_cast<double &>(i);
int *p = reinterp ret_cast<int *>(100);
return 0;
}
新特性
-
auto
:能自动推断出变量的类型; -
decltype(a)
:获取变量a的数据类型; -
nullptr
:解决NULL的二义性问题,针对空指针的; -
Lambda表达式
:本质就是一个函数,相当于OC中block;
#include <iostream>
using namespace::std;
int main(int argc, const char * argv[]) {
//本质是一个函数
int (*p)(int,int) = [](int a,int b) -> int {
return a + b;
};
cout << p(10,20) << endl;
return 0;
}
int main(int argc, const char * argv[]) {
int a = 10;
int b = 20;
//默认是值捕获
auto p = [a,b] {
cout << a << endl;
cout << b << endl;
};
//地址,引用捕获
auto p1 = [&a,&b] {
cout << a << endl;
cout << b << endl;
};
a = 11;
b = 22;
p();
p1();
return 0;
}
-
auto
类型推断,直接接收Lambda表达式;
int main(int argc, const char * argv[]) {
int a = 10;
int b = 20;
//默认是值捕获
auto p = [a,b] () mutable {
a++;
b++;
cout << a << endl; //11
cout << b << endl; //21
};
p();
cout << a << endl; //10
cout << b << endl; //20
return 0;
}
-
mutable
,可修改值捕获的变量值;
错误
- 变成过程中常见的错误类型:
- 语法错误;
- 逻辑错误;
- 异常;
异常
- 异常是一种发生在程序运行过程中发生的不好预测的错误,比如内存不足;
- 异常没有被处理,会导致程序闪退;
-
throw
抛出异常之后,会在当前函数查找匹配的catch
,找不到就中止当前的函数代码,去上一层函数中查找,若最终都找不到匹配的catch
,就会导致程序崩溃退出;
int main(int argc, const char * argv[]) {
try {
//内存溢出
for (int i = 0; i < 99999999; i++) {
int *p = new int[99999999];
}
} catch (...) {//捕获到异常
cout << "发生了异常" << endl;
}
return 0;
}
- 以上是系统抛出的异常;
-
catch (...)
拦截所有异常;
#include <iostream>
using namespace::std;
int divide(int a,int b){
//抛出异常 值为100 或者 "除数不能为0"
// if (b == 0) throw 100;
if (b == 0) throw "除数不能为0";
return a / b;
}
int main(int argc, const char * argv[]) {
try {
int m = 100;
int n = 0;
cout << divide(m, n) << endl;
} catch (int exception) {
cout << "捕获到异常: " << exception << endl;
} catch (const char *str) {
cout << "捕获到异常: " << str << endl;
}
return 0;
}
-
throw
抛出异常,catch
捕获处理异常;
智能指针
- 传统指针存在的问题:
- 需要手动管理内存;
- 容易发生内存泄漏;
- 释放之后变成野指针;
#include <iostream>
using namespace::std;
void test(){
throw 6;
}
int main(int argc, const char * argv[]) {
//异常导致内存泄漏
try {
int *p = new int();
test();
delete p;
} catch (...) {
cout << "发生异常" << endl;
}
return 0;
}
- 智能指针可解决传统指针存在的问题:
- auto_ptr:不推荐使用,存在缺陷不能指向数组;
- shared_ptr:属于C++11标准;
- unique_ptr:属于C++11标准;
#include <iostream>
using namespace::std;
class Person {
public:
Person(){
cout << "Person()" << endl;
}
~Person(){
cout << "~Person()" << endl;
}
};
int main(int argc, const char * argv[]) {
auto_ptr<Person> p(new Person());
return 0;
}
- 堆内存person对象,会自动释放,不用主动去调用delete函数了;
#include <iostream>
using namespace::std;
class Person {
public:
Person(){
cout << "Person()" << endl;
}
~Person(){
cout << "~Person()" << endl;
}
};
int main(int argc, const char * argv[]) {
shared_ptr<Person> p1(new Person());
shared_ptr<Person> p2(p1);
//shared_ptr指向数组
auto expr = [](Person *p){
delete [] p;
};
shared_ptr<Person> p3(new Person[5]{},expr);
return 0;
}
- 多个
shared_ptr
指针可以指向同一个对象,当最后一个shared_ptr
指针销毁时,指向的堆对象才会被销毁; - shared_ptr指向数组时,传入lambad表达式,释放所有堆对象;
- shared_ptr指针的原理与OC中的strong相似,强引用;
- 一个shared_ptr指针会对对象产生一个强引用,引用计数+1;
int main(int argc, const char * argv[]) {
shared_ptr<Person> p1(new Person());
shared_ptr<Person> p2 = p1;
shared_ptr<Person> p3= p1;
shared_ptr<Person> p4 = p1;
shared_ptr<Person> p5 = p1;
cout << p1.use_count() << endl; //5
return 0;
}
-
use_count
可获取对象有多少个shared_ptr指针引用; -
shared_ptr指针的循环引用
#include <iostream>
using namespace::std;
class Person;
class Car {
public:
// Person *m_person;
shared_ptr<Person> m_person = nullptr;
Car(){
cout << "Car()" << endl;
}
~Car(){
cout << "~Car()" << endl;
}
};
class Person {
public:
// Car *m_car;
shared_ptr<Car> m_car = nullptr;
Person(){
cout << "Person()" << endl;
}
~Person(){
cout << "~Person()" << endl;
}
};
int main(int argc, const char * argv[]) {
//循环引用 内存泄漏
shared_ptr<Person> person(new Person());
shared_ptr<Car> car(new Car());
person->m_car = car;
car->m_person = person;
return 0;
}
- 解决方案:采用弱引用,如下所示:
class Car {
public:
// Person *m_person;
// shared_ptr<Person> m_person = nullptr;
weak_ptr<Person> m_person;
Car(){
cout << "Car()" << endl;
}
~Car(){
cout << "~Car()" << endl;
}
};
-
weak_ptr
是弱引用; -
unique_ptr
也会对对象产生一个强引用,但同一时间只能有一个unique_ptr
指针指向堆对象; -
引用权限转移:调用std::move函数;
int main(int argc, const char * argv[]) {
//unique_ptr
unique_ptr<Person> p1(new Person());
//p2指向堆对象 p1不再指向了
unique_ptr<Person> p2 = std::move(p1);
return 0;
}
网友评论