--be217e4ab3d4e1bf x-next-cache-tags: _N_T_/layout,_N_T_/blog/layout,_N_T_/blog/[...slug]/layout,_N_T_/blog/[...slug]/page,_N_T_/blog/c%E8%AF%AD%E8%A8%80/%E5%BC%95%E7%94%A8%E4%B8%8E%E6%8C%87%E9%92%88%E7%9A%84%E5%8C%BA%E5%88%AB vary: RSC, Next-Router-State-Tree, Next-Router-Prefetch Pointer(指针)与引用的区别 | YBinary
Published on

Pointer(指针)与引用的区别

Authors

概念

引用:引用是某个变量的别名,一旦引用被初始化,它就不能再指向其他对象引用必须在声明时初始化

int a = 10;
int& ref = a;  // ref 是 a 的引用,ref 就是 a 的别名

指针:指针是存储某个变量地址的变量。指针可以在任何时候指向不同的对象,并且可以为空(即指向 nullptr)。

int a = 10;
int* ptr = &a;  // ptr 是指向 a 的指针,存储 a 的地址

底层实现

尽管 C++ 语法上将引用和指针区分开来,但在底层,引用通常是通过 指针 或 内存地址 来实现的。编译器在生成代码时,会将引用转换为指针或内存地址的操作。

2.1 引用作为指针处理

编译器通常会将引用视为指针的别名。这意味着引用在底层实际上是一个指向对象的指针,但编译器对引用进行了语法上的简化,使得程序员不需要显式地解引用。

例如,下面的代码:

int a = 10;
int& ref = a;
ref = 20;

可能会被编译器转换为类似以下的代码:

int a = 10;
int* const ref = &a;  // 引用被实现为指针
*ref = 20;            // 对引用的赋值被转换为对指针解引用的赋值

在这种情况下,ref 在底层被处理为一个指向 a 的指针,ref = 20 实际上是通过 *ref 来修改 a 的值。

引用的内存模型

引用本身并不占用额外的内存空间,它只是在编译时为某个对象创建了一个别名。因此,引用的内存地址与它所引用的对象的内存地址是相同的

例如,下面的代码:

int a = 10;
int& ref = a;

std::cout << &a << std::endl;   // 输出 a 的地址
std::cout << &ref << std::endl; // 输出 ref 的地址,和 a 一样

输出结果会显示 &a 和 &ref 是相同的地址,因为 ref 实际上是 a 的别名,它们指向同一个内存位置。

可通过该例题更深刻的理解

http://oj.lgwenda.com/problem/15 使用C++的引用,注意提交时把代码选为C++; 在主函数定义字符指针 char *p, 然后在子函数内malloc申请空间(大小为100个字节), 通过fgets读取字符串,然后在主函数中进行输出;要求子函数使用C++的引用, 注意在C++中从标准输入读取字符串,需要使用fgets(p,100,stdin)

#include <stdio.h>
#include <stdlib.h>

void get(char* &i) {
    i = (char*)malloc(100);
    fgets(i,100,stdin);
}

int main() {
    char* p = nullptr;
    get(p);
    printf("%s\n",p);
}

主要部分内容由chatGPT-4o-mini生成,如有错漏欢迎告知留言

--be217e4ab3d4e1bf--