指针和 引用 (一)
指针和引用的区别
-
非空区别. 在任何情况下, 都不能使用指向空值的引用, 一个引用必须总是指向某个对象. 而指针, 可为 NULL
-
合法性区别. 在使用引用前不需要测试其合法性. 相反, 指针应总是被测试, 防止其为空.
-
可修改区别. 指针可以被重新赋值, 而引用总是在初始化时被指定对象, 以后不得修改.
const 常量赋值时, 必须同时初始化.
effective C++ 讲到 const 声明和初始化的 item2 没太看懂
例题1:
1 // p 只是一个副本
2 void getMemory(char *p, int num) {
3 p = (char *)malloc(sizeof(char) * num);
4 }
5
6 // p 仍是一个副本, 但 *p 不是
7 void getMemory(char **p, int num) {
8 *p = (char *)malloc(sizeof(char) * num);
9 }
但更一般的解法是直接让 getMemory 返回指针
例题2:
/*
* str[] 是局部数组, 其有效域只在 strA 中
*/
char *strA() {
char str[] = "hello world";
return str;
}
/*
* char *str 分配的并不是局部数组, 而是全局数组
*/
const char* strB() {
char *str = "hello world";
return str;
}
int main() {
char c[15] = "hello world";
*c = 't'; // ok
char *d = "hello";
*d = 't'; // wrong! 存在只读数据段
return 0;
}
可在 strC() 中声明一个 static char str[], 同时满足全局和可修改
例题3:
int main() {
int a[3];
a[0] = 0; a[1] = 1; a[2] = 2;
int *p, *q;
p = a;
q = &a[2];
cout << q-p << endl;
return 0;
}
p, q 的实际地址值相差是 8, 但是 q-p 的结果却是 2.
q - p 的实际运算是 地址值之差/sizeof(int)
例题4:
struct S {
int i;
int *p;
};
int main() {
S s;
int *p = &s.i;
p[0] = 4;
p[1] = 3;
s.p = p;
s.p[1] = 1;
s.p[0] = 2; // 发生异常, 访问出错
return 0;
}
p[0] 就是 i, p[1] 是 *p
s.p = p; 那么 s.p 指向 &S.i
s.p[1] 指向 s.p, s.p[1] = 1 等价于 s.p = 1, 即现在指针 p 指向内存地址为 0x0000...1 的地方
s.p[0] = 2 就是要访问 0x000...1空间, 对一个未做声明的空间直接访问, 所以访问出错
例题5:
class A {
public:
int _a;
A() {
_a = 1;
}
void print() {
printf("%08x\n",&_a);
printf("%d\n", _a);
}
};
class B : public A {
public:
int _a;
B() {
_a = 2;
}
};
int main() {
B b;
b.print();
printf("%d\n", b._a);
printf("%08x\n",&b._a);
return 0;
}
结果时 0x...60, 1, 2, 0x...64
可见, 并没有发生内存覆盖.
另外, 在 B 内另外设置一个打印函数输出 _a, 结果是 2

浙公网安备 33010602011771号