NIUCLOUD是一款SaaS管理后台框架多应用插件+云编译。上千名开发者、服务商正在积极拥抱开发者生态。欢迎开发者们免费入驻。一起助力发展! 广告
# 1.3、复合类型 **复合类型**(compound type)是根据另一种类型定义的类型,C++ 有两种复合类型,分别是引用和指针。 > A**compound type**is a type that is defined in terms of another type. C++ has several compound types, two of which -- references and pointers. ## 引用 **引用**(reference)是对象的一个别名,通过定义引用可以减少值的拷贝。 > A **reference** defines an alternative name for an object, the compiler only binds the reference to its initializer instead of copying the initializer's value. 一个引用必须和它绑定的对象类型一致: ``` int &reval = 10; // error:绑定的不是一个对象 double dval = 3.14; int &reval = dval; // error:类型不对 ``` **引用通常用于**: * 函数参数列表:C++ 支持把引用作为参数传给函数,这样可以减少函数调用过程中参数拷贝的开销; * 函数返回值:这样做的优势在于内存中不产生返回值的副本,并且可用于左值运算; ## 指针 每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址。 **指针**是一个变量,其值为另一个变量的地址。当一个指针指向一个地址时,程序可以通过(*)运算符访问变量。 > A **pointer** holds the address of another object. **区别指针类型** * `int *p[10];`:长度为10的指针数组,数组中的每个变量为指向int的指针变量; * `int (*p)[10];`:一个数组指针,指向长度为10的int数组; * `int *p(int);`:函数声明,函数名是p,参数是int类型的,返回值是int指针类型的; * `int (*p)(int);`:函数指针,强调是指针,该指针指向的函数具有int类型参数,并且返回值是int类型的; ### 特殊指针 * **野指针**:指向已经被释放或回收的地址空间的指针。 * **空指针**:NULL 本质上是0,nullptr 则代表空指针。 ```c++ typeid(NULL).name(); // output: l typeid(nullptr).name(); // output: Dn ``` 为了避免不必要的麻烦,尽量使用 nullptr: ```c++ void func(void* t) { printf("func(void*)\n"); } void func(int i) { printf("func(int)\n"); } int main() { func(NULL); // 将导致编译不通过 func(nullptr); // 调用func(void*) return 0; } ``` **函数指针**是一个指向函数首地址的指针变量。C++ 在编译时,每一个函数都有一个入口地址,函数指针指向的就是这个入口地址。有了函数指针,可以通过指针来调用函数。 ```c++ int max(const int& lhs, const int& rhs) { return lhs > rhs ? lhs : rhs; } typedef int(*pf)(const int&, const int&); int main () { int (*f)(const int&, const int&); // 定义一个函数指针 pf p = max; printf("%d\n", p(1, 2)); printf("%d\n", (*p)(1, 2)); return 0; } ``` ### 数组名和指针的区别 * 数组名和指针都可以通过增减偏移量来访问数组中的元素; * 数组名不是真正意义上的指针,可以理解为常指针,所以数组名没有自增、自减等操作; * 当数组名当做形参传递给调用函数后,就失去了原有特性,退化成一般指针,多了自增、自减操作,但sizeof运算符不能再得到原数组的大小了; ## 指针和引用区别 * 引用只是别名,不占用具体存储空间,只有声明没有定义,而指针是具体变量,需要占用存储空间;所以使用 sizeof 看一个指针的大小是 4,而引用则是被引用对象的大小; * 引用在声明时必须初始化为另一变量,一旦出现必须为 `typename &refname = varname;`形式,而指针声明和定义可以分开,可以先只声明指针变量而不初始化,等用到时再指向具体变量; * 引用一旦初始化之后就不可以再改变(变量可以被引用为多次,但引用只能作为一个变量引用),而指针变量可以重新指向别的变量; * 不存在指向空值的引用,必须有具体实体,但是存在指向空值的指针; * 指针和引用使用自增运算符的意义不一样;