{ int i = 42; int &r = i; //紧随类型名出现,因此是声明的一部分r是一个引用 int *p; //紧随类型名出现,因此是声明的一部分,p是一个指针 p = &i; //&出现在表达式中,是一个取址 *p = i; //*出现在表达式中,是一个解引用 int &r2 = *p; //&是声明的一部分,*是解引用 }
生成空指针的方法
1 2 3 4 5
{ int p1 = nullptr;//int*p1 = 0;可以转换成任意其它类型的指针 int *p2 = 0; int *p3 = NULL; }
void* 指针是一种特殊的指针类型,可以存放任意对象的地址。
如何检查指针是否指向了一个合法的对象呢?
检查是否为NULL
1 2 3
if (p != NULL) { // p 可能是一个有效指针(但不保证) }
确保指针指向的是已分配的内存
1 2 3 4 5
p = malloc(sizeof(int)); p = newint; if (p) { // new 在分配失败时通常会抛出异常,除非使用 `nothrow` }
检查指针是否为悬空指针
1 2 3 4 5 6 7 8 9 10
int *p = (int*)malloc(sizeof(int)); free(p); // p 现在是悬空指针 if (p) { printf("p 不是 NULL,但仍然是无效的!\n"); } //处理方法 free(p); p = NULL; //智能指针 std::unique_ptr<int> p = std::make_unique<int>(10); // 自动管理内存
{ string s("my name"); auto it = s.begin(); *it = toupper(*it); }
在这种方式下要注意迭代器与指针的相似性与差异性
数组
数组是一种类似vector的数据结构,但是数组的大小不变,不能够随时向数组内添加元素。
在数组初始化的时候要注意字符数组的特殊,字符串字面值的结尾处还有一个空白字符。
对于复杂数组的理解(类型修饰符从右向左依次绑定)
1 2 3 4
int *ptrs[10];//10个整型变量数组指针 int (*Parray)[10] = &arr;//指向十个整型变量的数组的指针 int (&arrRef)[10] = arr;//引用十个整型变量数组 int *(&arry)[10] = ptrs;//arry是数组的引用,该数组含有10个指针