.
指针(pointer)是“指向(point to)”另外一种符合类型。与引用类似,指针也实现了对其他对象的间接访问。
指针与引用的区别:
其一:指针本身就是一个对象,允许指针复制和拷贝,而在指针的生命周期内可以先后指向几个不同的对象。
其二:指针无须在定义时初始值。
和其他内置的类型一样,在块作用域内定义的指针如果没有被初始化,也将拥有一个不确定的值。
指针的定义
1 | //定义 |
指针的四种状态
- 指向一个对象
- 指向紧邻对象所占空间的下一个位置
- 空指针,意味着指针没有指向任何对象。
- 无效指针,也就是上述的情况之外的其他值。(一般都是没有初始化的指针,指向一个垃圾值)
试图拷贝或以其他方式访问无效指针的值都将引发错误。
访问空指针和无效指针的后果是无法预计的。
指针 vs 对象
指针可以降低传输大数据时候的花销。
指针可以修改自己所指的对象(相同的类型)。
但是指针在使用前要更加小心,因为有可能会指向nullptr
,而直接使用对象就不会有这样的问题。
A pointer allows us to pass potentially large amounts of data around at low cost: instead of copying the data we simply pass its address as a pointer value. The type of the pointer determines what can be done to the data through the pointer. Using a pointer differs from using the name of an object in a few ways:
- We use a different syntax, for example, ∗p instead of obj and p−>m rather than obj.m.
- We can make a pointer point to different objects at different times.
- We must be more careful when using pointers than when using an object directly: a pointer may be a nullptr or point to an object that wasn’t the one we expected.
空指针
void*
void*
as pointer to an object of unknown type. void *
可以用来返回位置的类型,有点类似Objective-C的id类型。任何类型的指针都可以赋值给void *
类型。void *
也可以隐形的转为其他的类型。
nullptr
nullptr代表空指针, 使用nullptr
使代码比替代方法更具有可读性,并避免函数重载以接受指针或整数时潜在混淆。
在nullptr引入之前,都是直接使用0来代表空指针。
nullptr的优点是它没有整数类型。 说实话,它也没有指针类型,但您可以将其视为所有类型的指针。 nullptr的实际类型是std :: nullptr_t,并且在一个奇妙的循环定义中,std :: nullptr_t被定义为nullptr的类型。 类型std :: nullptr_t隐式转换为所有原始指针类型,这就是使得nullptr就像它是所有类型的指针一样的原因。
NULL
NULL
是一个宏,在不同的系统里面可能代表着不同的值。NULL
可能是0或者是0L,在C语言里面是(void*)0
1 | int *p1 = nullptr; |
空指针最直接的办法就是用字面值nullptr
来初始化。
NULL是一种定义在cstdlib的预处理变量来给指针赋值。
Pointer into Arrays
指针只能指向数组的第一个元素,所以程序员得自己维护数组的大小。
1 | int v[] = { 1, 2, 3, 4 }; |
有些算法在搜索元素位置的时候,如果没有找到,通常会把指针指向最后一个元素末尾一个不存在的位置。
Navigating Arrays
For every built-in array a and integer j within the range of a, we have:
1 | a[j] == ∗(&a[0]+j) == ∗(a+j) == ∗(j+a) == j[a] |