9.x - 小结与测试 - 引用和指针
复习
9.1 - 复合数据类型
- 复合数据类型 (也称作组合数据类型),指的是哪些由基础数据类型组成的数据类型(或由其他复合类型组成)。
9.2 - 值的分类(左值和右值)
- 一个表达式的值类别(value category)表明一个表达式最终会被解析为一个值、一个函数还是某种类型的对象。
- 左值表达式求值为一个具有标识的函数或者一个对象。一个对象具有标识,意味着它具有标识符或者一个具有标识的内存地址。左值有两个子类:可变左值是可以被修改的左值,不可变左值是不可以被修改的左值(通常因为它们是
const
或constexpr
类型的)。
- 当表达式不是左值时,它便是右值。包括字面量(字符串字面量除外)和函数或操作(当按值返回时)的返回值。
9.3 - 左值引用
- 引用是某个已经存在的对象的别名。引用一旦被定义,任何对引用的操作都相当于操作该引用所表示的对象。C++ 有两种引用,左值引用和右值引用。左值引用(简称引用)就是某个左值的别名。左值引用变量就是一个用作左值引用的变量,其引用的左值通常是另外一个变量。
- 当使用对象或函数对引用进行初始化之后,我们说该引用和对象或函数绑定了。被引用的对象或者函数称为referent。
- 左值引用不可以被绑定到不可修改的左值或右值(不然的话你就可以通过该引用来修改它们的值了,这违反了它们作为常量的属性)。因此,左值引用有时也被称为左值非常量引用(简称常量引用)。
- 引用一旦初始化,它便不能够被重置,也就是说不能修改它去引用别的对象。
- 当如果对象先于它的引用被销毁,则该引用会指向一个不存在的对象,此时该引用被称为悬垂引用。访问悬垂引用会导致未定义行为。
9.4 - const类型的左值引用
- 当使用
const
关键字来修饰一个左值引用时,即要求该引用将它所引用的对象看做常量。此时成该引用为指向常量值的左值引用(简称指向常量的引用或常量引用)。常量引用可以被绑定到可以修改左值,不可修改左值和右值。
- 一个临时对象(有时称为未命名对象或匿名对象)是指在一个单一表达式中为了临时使用而创建的对象(使用后销毁)。
9.5 - 传递左值引用
- 当进行按引用传递时,我们将函数的形参声明为引用或常量引用而不是普通的变量。当函数被调用时,形参中的引用会绑定到实参。因为引用只是对象的别名,所以这种情况下并不会创建实参的拷贝。
- 取地址运算符 (&)会返回其操作数的地址。而解引用(*)运算符则会返回给定地址存放的左值。
9.6 - 指针简介
- 指针是一个对象,它持有一个内存地址(通常是另外一个变量的地址)作为其值。使用指针我们可以将某个对象的地址保存起来以便稍后使用。和不同的变量一样,指针不会被默认初始化。而没有被初始化的指针通常被称为野指针。悬垂指针则是那些保存着无效地址的指针(该地址中的对象已经被销毁)。
9.7 - 空指针
- 除了内存地址,指针还可以保存一个特殊值,即空值(null)。null是一个特殊值它表示空值。当指针的值为null时,表示它没有指向任何地址。此时该指针被称为空指针。关键字
nullptr
是空指针的字面量。我们可以通过nullptr
来显式地为指针初始化或赋值为空值。
- 指针应当持有一个包含有效对象的地址,或者设置为
nullptr
。这种情况下我们只需要判断指针是不是空即可,否则我们就认为它是有效的。
9.8 - 指针和const
- 指针如果指向一个const常量(有时简称为指向常量的指针),则表示一个(非常量)指针指向一个常量。
- 而一个常量指针,则是在其持有地址被初始后,不能再改变的指针。
- 指向常量的常量指针,其指针本身所持有的地址不能改变,也不能修改该地址所指向的对象。
9.9 - 按地址传递
- 对于传地址来说,调用者会使用对象的地址(通过指针)而不是对象本身作为实参。该指针(持有该对象的地址)会被拷贝到被调函数的指针参数(形参),该参数此时保存着该对象所在地址(的一份拷贝)。随后,函数可以对该指针进行解引用以访问该对象。
9.10 - 按地址传递 Part2
- 按引用返回时,函数返回绑定到返回对象的引用,这种情况下不会对返回值进行拷贝。在返回引用时,有一点需要注意:该引用所绑定的对象其生命周期要比函数长。否则返回的引用将变成悬垂引用(引用的对象被销毁了),此时继续使用该引用会导致未定义行为。如果实参通过引用的方式被传入,那么使用按引用返回该参数也是更安全的。
9.11 - 按引用返回和按地址返回
- 如果一个函数返回引用,且该引用被用来初始化或赋值给一个非引用类型的变量,那么该返回值会被拷贝(和按值返回的效果是一样的)。
- 按地址返回和按引用返回的工作原理几乎是一样的,区别只在于前者返回的是指向对象的指针而后者返回的是一个对象的引用。
9.12 - 指针、引用和const的类型推断
- 使用
auto
进行类型推断时,它会移除引用标记或其他顶层常量修饰符。如果,你仍需要这些标识符,则需要将其作为变量声明的一部分进行添加。
Back to top