【c++基础系列】指针和引用
大家好,我是Lampard~~
欢迎来到c++基础系列的博客
前文再续,书接上一回。今天和大家讲解一下c++中指针和引用的区别
因为博主我大学第一门课是学c,这也导致了我产生一个很严重的误区,指针就是引用。
还记得当时的代码是这样的:
void add1(int num) {
num = num + 1;
}
void add2(int* num) {
*num = *num + 1;
}
int main () {
int a = 0;
int b = 0;
add1(a);
add2(&b);
print(a); // 结果为0
print(b); // 结果为1
}
当时老师告诉我们,第一种是传值,第二种是传引用,传值不能改变原有变量,传引用能够改变原有变量。于是乎我就一直认为带*号的都是能改边原有变量的存在。
在c++,虽然记录的都是对象的地址,但指针和引用指代的并不是同一个东西。
相同点:
- 1). 都是地址的概念;
- 2). 都是“指向”一块内存。指针指向一块内存,它的内容是所指内存的地址;而引用则是某块内存的别名(我就是那一块内存,我指我自己);
- 3). 引用在内部实现其实是借助指针来实现的,一些场合下引用可以替代指针,比如作为函数形参。
不同点:
- 1). 指针是一个实体(新增空间地址),而引用仅是个别名(创建多个引用都不会新增地址,因为都是同一地址的别名而已);
- 2). 引用只能在定义时被初始化一次,之后不可变;指针可变;引用“从一而终”,指针可以“见异思迁”;
- 3). 引用不能为空,指针可以为空;
- 4). “sizeof 引用”得到的是所指向的变量(对象)的大小,而“sizeof 指针”得到的是指针本身的大小;
- 5). 指针和引用的自增(++)运算意义不一样;
- 6). 引用是类型安全的,而指针不是 (引用比指针多了类型检查)
实际踩坑的例子QAQ:
当时我是想要实现这一道算法题,然后我写下以下的代码:
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode();
ListNode* curNode = head;
while (l1 && l2) {
ListNode* tmp = l1->val < l2->val ? l1 : l2;
curNode->next = tmp;
tmp = tmp->next;
curNode = curNode->next;
}
curNode->next = l1 ? l1 : l2;
return head->next;
}
我的思路是用tmp来记录当前比较大的结点,然后把该结点的值链接到答案中后,让tmp = tmp->next让当前结点比较大的链表向下移动一个位置。但是问题就出现在这里,因为我的tmp是指针类型,tmp = tmp->next并不能让l1或者l2指向下一位置(引用才能做到这个功能),从而链表一直不往下走造成死循环。
ListNode* mergeTwoLists(ListNode* l1, ListNode* l2) {
ListNode* head = new ListNode();
ListNode* curNode = head;
while (l1 && l2) {
ListNode** tmp = l1->val < l2->val ? &l1 : &l2;
curNode->next = *tmp;
*tmp = (*tmp)->next;
curNode = curNode->next;
}
curNode->next = l1 ? l1 : l2;
return head->next;
}
于是乎我修改代码,把tmp改成**类型,变成了l1或者l2的引用,这样子*tmp = (*tmp)->next;就可以让链表移动一个结点,于是能实现功能,详细的解题过程在以下的博客中。