指针和引用的区别
-
非空区别. 在任何情况下, 都不能使用指向空值的引用, 一个引用必须总是指向某个对象. 而指针, 可为 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 ",&_a); printf("%d ", _a); } }; class B : public A { public: int _a; B() { _a = 2; } }; int main() { B b; b.print(); printf("%d ", b._a); printf("%08x ",&b._a); return 0; }
结果时 0x...60, 1, 2, 0x...64
可见, 并没有发生内存覆盖.
另外, 在 B 内另外设置一个打印函数输出 _a, 结果是 2