0. 什么是指针
指针是C++中的一种复合类型,是“指向(pointer to)”另外一种类型的复合类型,实现了对其他对象的间接访问。
它与引用的不同点在于,指针是一个对象,引用不是。
指针的内容是被指向对象的地址。
int a = 10;
// 指向a的指针,p中存放的是a的地址
int *p = &a;
关于指针,需要了解如下内容:
- 指针的声明
- 指针的初始化
- 指针的值
- 指针的拷贝&赋值
- 指针的使用
- 指针与const
1. 指针的声明
使用*
搭配其他数据类型,可以声明一个指针。
int *p;
char *s;
double *d;
2. 指针的初始化
若声明的指针没有初始化,它将执行默认初始化,它的值是一个不确定的值。
我们使用取地址运算符&
得到对象的地址,来给指针进行初始化。例如:
int a = 10;
// &a得到a的地址
int *pa = &a;
我们通过解引用运算符*
来得到指针所指向的对象的内容。
cout << *pa; // 输出10
若要输出指针的内容,可以直接使用:
cout << &a; // 输出0x7ffee109f828
cout << pa; // 输出0x7ffee109f828
3. 指针的值
3.1 四种类型
指针在程序任意时刻,只有四种类型的值:
- 指向一个对象
- 指向紧邻对象所占空间的下一个位置,例如尾后指针
- 空指针,意味着指针没有指向任何对象
- 无效指针,也就是上述情况之外的其他值
上述4条:
- 1-3的指针是有效的,4是无效的
- 1是访问安全的,2-4是访问危险的。
- 3作为判断语句的输入为
false
,其余都为true
int a = 10;
int arr[3] = {0, 1, 2};
// 1. 指向一个对象
// 此时指针是有效的,访问是安全的
int *pa = &a;
// 2. 尾后
int *parr = arr + 3;
parr = std::end(arr); // 推荐
// 3. 空指针
pa = nullptr; // 推荐使用nullptr
pa = 0;
parr = NULL;
// 4. 无效指针
MyClass *pp = new MyClass();
delete pp;
// 此时,pp是无效的,访问pp非常危险
养成良好的习惯,除非你胸有成竹,否则访问指针前都判断一下。
3.2 nullptr
nullptr
是C++11新引入的,一种特殊的字面值,它可以转换为任意类型的指针。
过去我们使用预处理变量NULL
来代表空指针,实际上它是定义在cstdlib中的宏定义,它的值是0。
这样会出现一个问题,当我有一些重载的函数:
void func1(int *p, bool flag); // 重载版本1
void func1(int a, bool flag); // 重载版本2
当我如下方式使用时:
func1(NULL, true); // 我想调用第1个重载版本
因为NULL
会在编译时被显示替换成字面值0,根据函数匹配规则永远会匹配到第2个版本,与我本来的意思相违背。
但是使用nullptr
则不同:
func1(nullptr, true);
因为nullptr
可以转换为任意类型的指针,在匹配时优先匹配到重载版本1,符合程序员的本意。
4. 指针的拷贝&赋值
与引用不同,允许指针的拷贝和赋值。
int a = 10, b = 20;
int *p = &a; // 初始化指针指向a
int *pt = nullptr;
// 将指针指向b
// 赋值操作
p = &b;
// 指针指向b
// 拷贝操作
pt = p;
5. 指针的使用
5.1 基本应用
之前提到过,通过解引用运算符*
实现对指向对象的间接访问。
解引用运算符得到的是左值,因此可以直接拿来赋值:
int a = 10;
cout << a << endl; // 输出10
int *p = &a;
*p = 20;
cout << a << endl; // 输出20
5.2 函数参数
函数参数可以传递指针,传递参数的行为和其他非引用类型是一样的,即值传递,拷贝的实际上是指针的值,因此可以实现在函数内部修改外部对象的功能。
void reset(int *buff_size) {
*buff_size = 256;
}
int main() {
int buff_size = 1024;
reset(&buff_size);
cout << buff_size; // 输出256
}
6. 指针与const
指针与const
的问题,产生的原因就是指针是对象。const既可以修饰指针本身,也可以修饰指针指向的情况,分别称作顶层const和底层const。
详细内容,请参考【C++深陷】之“const”。
7. 总结
指针是C++中的一种复合类型,是“指向(pointer to)”另外一种类型的复合类型,实现了对其他对象的间接访问。
指针要注意它本身是一个对象,因此存在指针的引用、指针的指针。
程序任意时刻,指针的值只有四种类型。要尽量使用nullptr作为空指针的定义。
指针的拷贝和赋值,和其他非引用类型一样,函数传递参数也是值传递,即传递的是指针的内容,某对象的地址。