C++ 知识总结 P01:类型系统
静态类型与动态类型
编程语言的类型系统有静态类型与动态类型之分。静态类型的编程语言在编译期间会进行类型检查,如果编译期间发现类型不匹配或类型未知,编译器就会报出对应的语法错误;动态类型的编程语言在运行期间才会确定常量变量类型,因而更加灵活。
静态类型与动态类型各有优势。静态类型的编程语言要求编程人员为每一个变量指定类型,同时编译器会进行类型检查,能减少代码中的错误。而使用动态类型编程语言的编程人员,在代码期间无需考虑类型问题,可以更高效地专注在解决问题上。另外,动态类型的编程语言在运行时要进行类型的推断,使这种语言编写的程序的执行效率不高,相比之下,使用静态类型编程语言编写的程序具有更高的执行效率。动态类型的语言如Python多用与脚本、原型验证等对执行效率要求不高的场景,静态类型的语言如C++、Java等更常用于工程实现等场景。
基本类型
在C++中常用的基本类型有以下几种:
-
bool
:存放布尔值的类型,本质上是一种整数类型。std::cout << static_cast<int>(false); // --> 0
-
char
,wchar_t
:wchar_t
可用于储存Unicode字符。 -
short
,int
,long
,long long
:默认的整数类型是有符号的,使用unsigned
获得无符号的整数。 -
float
,double
:默认的浮点数字面值是double
类型的,在使用浮点数时,推荐优先考虑使用double
类型。在图形学中为节省存储资源,会优先使用float
类型,精度也满足要求。 -
void
复合类型
-
指针 :空指针推荐使用
nullptr
代替以前的NULL
。 -
引用 :引用即别名,引用无法变更指向的变量,因此要求引用声明时就要初始化。引用不是对象,故不存在引用的数组,不存在指向引用的指针,不存在引用的引用。
指针和引用都可以作为函数的参数和返回值。当函数参数为变量本身时,会发生参数的拷贝。如果函数参数为中大型的数据结构时,在调用函数时拷贝参数的代价太高。传引用参数和传指针参数都可以避免这种情况。因此通常当函数参数为基本类型时,推荐使用传值参数;当函数参数为容器、类等自定义的数据结构时,推荐使用传引用参数。
另外,使用传引用参数和传指针参数,函数内部的代码可能会对引用、指向的外部变量产生影响,当函数需要改变这些变量时,可以直接使用传引用参数和传指针参数,否则,为防止不可预期的影响,应使用
const type& ref
和const type* pointer
。返回引用和指针的函数,需要注意返回的引用和指针不能指向函数内的局部变量。这些局部变量在函数运行结束后会被销毁,造成引用和指针悬垂。
-
数组 :尽管C++中提供了数组,但是推荐优先使用标准库中的容器。
-
函数 :函数指针多用于函数式编程或回调函数这些情况。
bool cmp(string& s1, string& s2) {return s1.size() < s2.size();} bool (*pf)(string& s1, string& s2); // 函数指针的声明 pf = cmp;
-
类
-
枚举 :使用枚举类型定义系列常量是一种非常好的方法,如定义多种颜色、定义多种选项等。
enum Color { red, green, blur, yellow }; Color tmp = red; // Color 作为一种类型使用。
枚举类型的本质是整数。
类型转换
一些基本类型间存在隐式类型转换,比如整数扩展为浮点数这种不会损失精度的转换。某些情况下需要进行强制类型转换。(见《游戏开发:世嘉新人培训教材》)
static_cast<type>(var)
:标准的转换,最主要使用的类型转换。reinterpret_cast<type>(var)
:不同类型的指针间的转换。const_cast<type>(var)
:不改变类型,只去除const
属性。dynamic_cast<type>(var)
:将基类指针转换为派生类指针。
类型别名
在C语言中,使用 typedef
进行类型别名的定义。在C++中,使用 using
关键字定义类型别名。
using Length = unsigned int;