这是我参与11月更文挑战的第5天,活动详情查看:2021最后一次更文挑战
指针
提到C与C++,我就会想到指针。虽然对闻指针之名已久,也大概了解过它的作用,但在以前的脚本语言编程过程中从未实际接触过指针以及其对应的内存管理。
先上指针与和它关系密切的引用的用法:
int updates = 6;
int * p_updates;
p_updates = &updates; //将变量updates的地址分配给p_updates
在了解更多关于指针的内容前,可以探讨下指针在C与C++中的意义,在C++ premier plus第四章中,有整整三节都用来介绍指针,其中开头关于指针设计哲学的表述很有意思。事实上,在上面的例子中,如果单单要获取某个量的地址,&updates也就足够了,而其实*p_updates也即为6,但C++ premier plus这样说:在计算机程序设计中,一个变量有其三要素:
- 变量的值
- 变量的类型
- 变量存放的位置
而在
C与C++中,变量的值与位置是被放在同等级别上的,被认为是一个硬币的两面(图源C++ premier plus),这也许就是其语言精髓的一部分吧。
指针类型
回到指针的使用,聊聊指针本身的类型,指针被认为是一种复合类型,C++程序员们常会这样编写程序:
int* p1, p2;
long* p3;
p1 = 0xB8000000; // 类型错误
pt = (int *) 0xB8000000; // 这样赋值类型才匹配
int*和long*意味指向int类型变量的指针和指向long类型变量的指针(事实上*前后的空格没有硬性要求)。
一种危险的使用指针的方法如下:
int* a_ptr;
*a_ptr = 6657;
事实上这样做语法上是没问题的,但是不像前文那种常见的初始化手法,这样做并没有给该变量一个可控的地址,在执行*a_ptr = 6657;语句的时候,a_ptr指向的变量可能被放到任何的位置(包括已经在使用的内存空间),这样的后果显然极不可控且糟糕。
另外,也可以用new操作符来进行指针初始化:
int * pt = new int;
*pt = 1001;
这样的操作就不会像上面的危险操作一样,实际上pt被指向一个int对象。
不恰当的指针初始化存在危险,但取址操作并不是这样(int &a; 这样的操作是不被允许的),那么其实引用其实可以作为指针的一个替代品,只需注意引用不能改变其指向的对象,引用一个很好的例子:
int a = 1;
int b = 2;
int &r = a; //初始化引用r指向变量a
int *p = &a; //初始化指针p指向变量a
p = &b; //指针p指向了变量b
r = b; //引用r依然指向a,但a的值变成了b
最后据说在编译器层面引用是指针的语法糖,表示还没学到那块,日后求证。