指针的简介
计算机程序本质上是对存储在内存中的数据进行的一系列操作。既然要对数据进行操作,首先要解决的第一个问题就是数据存储在什么地方?
一般情况下我们通过int x = 10;
来定义一个变量,可以通过x
来直接访问该变量存储的值,而指针提供了另外一种访问该变量存储的值的方法int* p = &x; *p;
。基于此,我们可以直接给出指针的定义:
指针的定义:指针是一个变量,其存储的是值的地址,而不是值本身。
指针的初始化
int x = 10;
int* p_x = &x; // 定义一个指向变量x的整型指针变量p_x
int* p_x; // 不能直接这么定义。这样会随机指向一个内存地址,很危险
int* p_x = 10; // 不能被定义为指向一个右值,因为它们没有确定的地址
cout << "value of x: " << x << endl;
cout << "value of x: " << *p_x << endl;
cout << "address of x: " << &x << endl; // &操作符取x的地址
cout << "value of p_x: " << p_x << endl; // p_x的值是x的地址
cout << "address of p_x" << &p_x << endl;
int* p = &x;
指针在初始化时就要定义为指向一个确切的地址
- 不能指向一个右值,例如
int* p = 10;
因为没有被分配内存空间 - 也不能初始化成一个野指针,例如
int* p_x;
可以在全局变量中这么定义,自动指向0
指针的类型
指针的类型必须要与所指向的变量类型一致。
- 因为指针指向的是变量的首地址,因此需要同指向的变量类型相同,这样才能通过解引用操作符
*
取到完整的值 - 指针所占的内存大小是固定的值,与其所指向的类型无关
测试代码:
int x = 10;
int* p_x = &x;
char y = 's';
char* p_y = &y;
cout << "size of p_x: " << sizeof(p_x) << endl;
cout << "size of p_y: " << sizeof(p_y) << endl;
cout << "size of int: " << sizeof(x) << endl;
cout << "size of char: " << sizeof(y) << endl;
// ******************OUT************* //
size of p_x: 8
size of p_y: 8
size of int: 4
size of char: 1
指针的常用操作
指针的常见操作是:解引用,增加,减少判等
cout << p_x << endl;
p_x = p_x + 1; // +1相当于在内存空间上加了一个int型变量的尺寸
cout << p_x << endl;
p_x = p_x - 1;
cout << p_x << endl;
int* q_x = &x;
cout << (p_x == q_x) << endl; // bool变量隐式转换为1
// ******************OUT************* //
000000A506B5F804 // 变量原本的地址
000000A506B5F808 // 变量加上一个整型变量尺寸后的地址
000000A506B5F804
1
指针与引用
引用从概念上可以简单地理解成为变量的别名,比如一个人大名叫李红军,在家里会被叫做李老四,其实指代地都是同一个人,叫法不同而已。
int x = 10;
int* p_x = &x;
int& ref_x = x;
cout << "value of x: " << x << endl;
cout << "value of ref_x: " << ref_x << endl; // 直接得到x的值
cout << "value of p_x: " << p_x << endl;
cout << "value of *p_x: " << *p_x << endl; // 使用解引用*之后得到x的值
cout << "address of x: " << &x << endl;
cout << "address of ref_x: " << &ref_x << endl;
// ******************OUT************* //
value of x: 10
value of ref_x: 10
value of p_x: 000000247C1FF594
value of *p_x: 10
address of x: 000000247C1FF594
address of ref_x: 000000247C1FF594
A reference is essentially identical to the object being referenced. 引用本质上与被引用的对象相同
- 引用的出现纯粹是为了优化指针的使用,而提出的语法层面的处理。比指针使用起来更加安全,不会出现解引用空指针,野指针的情况
- 引用实现原理上完全等价于指针。在编译器内部一般将其实现为一个const 指针。c++中的引用一旦初始化,就不能重新定位,这意味着它不能被更改为引用另一个对象
- 引用对于传递对象参数有非常大的优化和好处。
- 引用有其局限性,与指针相比,有时候可能与面向对象的设计有冲突