【Cpp】指针与引用

前言

在C语言中,我们对指针的规范并不严谨------我们常常会用void*来传入一个不知道其变量类型的指针,为了兼容CCpp允许这样的语法存在,但是,由于这样的指针不具有安全性,我们无法通过*来解引用void*,这就需要用到我们的显式转换 。为了方便看指针的引用而不是由一堆*组成了参数和参数类型,我们采用引用来让这种写法变得更加简洁;

文章目录

指针

什么是指针?指针是一个数字,是一个存储内存地址的数值。 指针是用来给我们取址用的操作,方便我们对数据的读取和写入,因为我们在代码中所做的每一件事,都是从内存中读取或写入内存------类型只是我们虚构出来的东西,好让我们这群写程序的知道这个指针到底有多少个字节组。

cpp 复制代码
//The Example is from the Cherno
#include<iostream>

int main(){
    void* ptr=0;//我们就这样创造出来了第一个指针变量
    //std::cin.get();
    return 0;
}

内存地址不会是00是无效的一个数值,我们也用NULL来表达其值为空,对于指针来说,无效是一个完全可以接受的状态 ,++人家接受得了许多失败++ ,但是,很遗憾的是,0既然意味着没有,那么就是说该数值无法读取或写入。

当然,#defined NULL 0说明了在预处理器上NULL就被处理成了0,我们在C++11引入了一个新的概念,称之为nullptr

请避免将 NULL 或零 (0) 用作 null 指针常量;nullptr 不仅不易被误用,并且在大多数情况下效果更好。

例如,给定 func(std::pair<const char *, double>),那么调用func(std::make_pair(NULL, 3.14)) 会导致编译器错误。 宏 NULL 将扩展到 0,以便调用std::make_pair(0, 3.14)将返回 std::pair<int, double>,此结果不可转换为 funcstd::pair<const char *, double> 参数类型。

调用 func(std::make_pair(nullptr, 3.14)) 将会成功编译,因为 std::make_pair(nullptr, 3.14) 返回 std::pair<std::nullptr_t, double>,此结果可转换为 std::pair<const char *, double>

------From nullptr, the pointer literal (since C++11) - cppreference.com

类型完全不会影响指针

我们有:

cpp 复制代码
#include<iostream>

int main(){
    int var=23;
    void* ptr=&var;
    return 0;
}

这个时候void*可以接收到varint类型变换,

cpp 复制代码
#include<iostream>

int main(){
    int var=23;
    double var=(double)&var;
    return 0;
}

我们会发现在指针中获得的地址还是跟先前从void*中读取到的int的数值一样,这就证明了指针类型只是一种辅助工具,帮助我们和编译器去理解这个变量的类型。

cpp的强制转换类型是比c语言灵活一点 double(var)也可以。

我们解引用 告诉编译器,这是一个intshortlonglong的变量,这样我们好确定我们的如何从内存中读取计算出我们的数值。

当然,我们可以利用char*new关键字来确定一个内存大小。

cpp 复制代码
#include<iostream>

int main(){
    char* buffer=new char[8];
    memset(buffer,0,sizeof buffer);
    
    char** ptr=&buffer;
    
    delete[] buffer;//用完后删除
    return 0;
}

引用

引用(Reference)实际上是指针(Pointer)的一个扩展,我们如何写他们,和应用他们都有所不同,但是,本质上他们并无二异义,并且引用只能算一种语法糖

cpp 复制代码
#include<iostream>

int main(){
    int a=5;
    int& ref=a;//ref这个'变量'其实是引用。
    ref=2;//实际上就是'变量'a这个主体变成了2.
    return 0;
}

就好比说,我叫MongXin,但是我身份证不叫MongXin,在警察局里找不到MongXin,却不能说明这个引用不存在------同样的,申明完一个引用后,其并不真实存在,但是其就是那个变量的别名 ;我可以注册一个电话号码,注册完之后它即属于我身份证上的名字,也属于MongXin ,同样的,ref就是有这样的作用,我们可以把它当a使用。

&不可更改

就像你有好几个好朋友,但是你能把好朋友A的别名冠给好朋友B吗?这本身算是一种不礼貌的行为,我们的Cpp是一位绅士,拒绝这种情况的发生。

cpp 复制代码
#include<iostream>

int main(){
    int a=5;
    int b=8;
    int& ref=a;//ref这个'变量'其实是引用。
    int& ref=b;//ERROR
    return 0;
}

这点跟指针的const void*一样,我们无法更改我们指向的内存空间,但是不妨碍我们把我们的家具挪一挪变成一个新的数值。

pass-by-value和pass-by-reference

如果我们有:

cpp 复制代码
#include<iostream>

void Increment(int val){
    val++;
}

void log(int val){
    std::cout<<val<<endl;
}

int main(){
    int a=5;
    Increment(a);
    log(a);
    return 0;
}

我们会发现打印出来的数值是5,并没有增加,而我们稍微动脑筋就知道,这个时候val是一个局部变量,它是copy出来的一份数据,局部变量传不出去,我们将这种引用数值的方式称之为Pass-by-valuePass-by-value 在不需要更改数值的时候可以使用,但是在我们对数值需要更改的情况下就显得笨拙,这时候我们采用------一种引用地址的方式,Pass-by-reference

cpp 复制代码
#include<iostream>

void Increment(int* val){
    (*val)++;
}

void log(int val){
    std::cout<<val<<endl;
}

int main(){
    int a=5;
    Increment(&a);
    log(a);
    return 0;
}

我们也存在利用引用的情况:

cpp 复制代码
#include<iostream>

void Increment(int& val){
    val++;
}

void log(int val){
    std::cout<<val<<endl;
}

int main(){
    int a=5;
    Increment(a);
    log(a);
    return 0;
}

通过引用,我们会发现我们重写了这段代码,但是在编译后,我们得到的代码是一样的,只不过我们的源码现在看起来很容易懂。

二者差异

唯二的区别就是,写法不一样,以及引用名并不真实存在。

如果通过指针:

cpp 复制代码
void log(*val){}//这里是解引用

int val=3;
int* ptr=&val;
log(ptr);//相当于log(&val);

如果通过引用:

cpp 复制代码
void log(&val){}//这里是&

int val=3;
log(val);

写在后面

我们发现CppC本质上还是有差别的,一些C里面麻烦的东西在Cpp中得到了优化,而且Cpp还可以兼容运行C,这就说明了Cpp的兼容性高,这也是我们下一篇章的的重点。

相关推荐
飞升不如收破烂~1 小时前
redis的map底层数据结构 分别什么时候使用哈希表(Hash Table)和压缩列表(ZipList)
算法·哈希算法
九圣残炎1 小时前
【从零开始的LeetCode-算法】3354. 使数组元素等于零
java·算法·leetcode
寒笙LED1 小时前
C++详细笔记(六)string库
开发语言·c++·笔记
程序猿小柒2 小时前
leetcode hot100【LeetCode 4.寻找两个正序数组的中位数】java实现
java·算法·leetcode
雨中rain2 小时前
贪心算法(1)
算法·贪心算法
不爱学习的YY酱2 小时前
【操作系统不挂科】<CPU调度(13)>选择题(带答案与解析)
java·linux·前端·算法·操作系统
平头哥在等你2 小时前
求一个3*3矩阵对角线元素之和
c语言·算法·矩阵
飞滕人生TYF2 小时前
动态规划 详解
算法·动态规划
_OLi_2 小时前
力扣 LeetCode 106. 从中序与后序遍历序列构造二叉树(Day9:二叉树)
数据结构·算法·leetcode
ahadee3 小时前
蓝桥杯每日真题 - 第18天
c语言·vscode·算法·蓝桥杯