上了课后感觉常量和指针之间的各自组合都挺绕的,写点东西来理一下方便以后复习吧。

常量指针 链接到标题

又称禁写间接指针、指向 const 的指针

声明语句:

const int *p;

(以下都int类型为例)

特点 链接到标题

不能改写此类指针的间接引用,即 *p = 8; 这样的语句是非法的。

但此类指针并未禁写,所以可以修改指向。

常指针 链接到标题

又称禁写指针、指针常量

声明语句:

int r = 6;
int *const p = &r;

特点 链接到标题

此类指针是不能改写的,它在赋初值以外无法修改指向的,所以在声明此类指针时必须要赋初值。p = &l; 是非法的。

但它的间接引用没有被禁用,所以 *p = 8; 是合法的。

禁写指针又禁写间接引用 链接到标题

声明语句:

int r = 6;
const int *const p = &r;

特点 链接到标题

此类指针即不能修改指向,也不能改写间接引用,所以

p = &l;
*p = 8;

都是非法的。

三者互相赋值 链接到标题

int a, b, c, d;
int *p1 = &a;
int *const p2 = &b;
const int *p3 = &c;
const int *const p4 = &d;

p1 = p2; // success
p1 = p3; // error
p1 = p4; // error
p2 = p1; // error
p2 = p3; // error
p2 = p4; // error
p3 = p1; // success
p3 = p2; // success
p3 = p4; // success
p4 = p1; // error
p4 = p2; // error
p4 = p3; // error

可以改写间接的指针的内容是可以赋值给禁写间接的指针,但禁写间接的指针的内容是不能赋值给可以改写间接的指针,因为这样违背了数据的安全性原则。

引用 链接到标题

声明语句:

int r = 6;
int &p = r;

引用就是一种指针常量,即 int &p = r;int *const = &r; 是等价的。

int &p = 6; 是非法的,因为引用本质上的对一块已有的内存取别名,而一个值是没有内存空间的,所以无法被引用。

通过取地址符我们可以发现, rp 指向的地址是同一个。

&操作符 链接到标题

当&a前面 有类型符 时,它必然是对引用的声明;

当&a前面 无类型符 时,则是取变量的地址(取地址符)。

引用作为函数变量 链接到标题

int fun(int *a, int *b);

虽然这样声明的函数可以通过函数内部的逻辑语句修改实参的值,但本质上依旧是值传递,这里传的值便是变量的地址,而且从代码的健壮性考虑,这里传入的地址是需要判断是否为野值的(if(a)),更加复杂。

int fun(int &a, int &b);

这样声明的函数是真正的址传递,因为a和实参指向的内存空间是同一个,并且不用在函数内部逻辑语句中判断传入的是否为野值(野指针)。

函数返回值为引用 链接到标题

一般的函数返回值是不能作为左值的,但如果返回的是引用就可以了。

int r = 6; // 全局变量
int &fun1() {
    return r;
}
int &fun2() {
    static int l = 8;
    return l;
}

只有这样声明的两个函数(全局变量或静态变量)是满足返回的是引用的,所以

fun1() = 2;
fun2() = 2;

这样两条语句是合法的,2 最终会赋给函数传回来的引用。

这里运算的流程是先分别将等式左右的表达式算好,然后再将右式的结果赋给左式最终返回的引用。

常引用 链接到标题

声明语句:

int r = 6;
const int &p = r;

这样的引用和禁写指针又禁写间接引用一样,这时的引用是可以引用一个数值的。

两种引用直接的互相赋值和指针类似,非常引用可以作为初值赋给常引用,但常引用不可以作为初值赋给非常引用。

函数指针 链接到标题

声明语句:

void (作用域::*p)();

这样定义的p指针是一个指向无参无返回值函数(当然也可以是有参有返回值的,只需像写普通函数一样加上就好)的指针。

因为每一个函数都是储存在内存上的一段代码,所以我们可以将这一段代码的首地址(即函数名称指针所指向的地址)赋给函数指针,之后便可以调用函数指针来执行对应函数了,如:

int (*p)(int, int) = &max;
int a, b, c, d;
d = p(p(a, b), c); // 等价于 d = max(max(a, b), c);

函数指针可以实现回调函数