【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的兼容性高,这也是我们下一篇章的的重点。

相关推荐
我不是代码教父6 分钟前
[原创](Modern C++)现代C++的关键性概念: 流格式化
c++·字符串格式化·流格式化·cout格式化
利刃大大23 分钟前
【回溯+剪枝】找出所有子集的异或总和再求和 && 全排列Ⅱ
c++·算法·深度优先·剪枝
子燕若水41 分钟前
mac 手工安装OpenSSL 3.4.0
c++
*TQK*1 小时前
ZZNUOJ(C/C++)基础练习1041——1050(详解版)
c语言·c++·编程知识点
Rachela_z1 小时前
代码随想录算法训练营第十四天| 二叉树2
数据结构·算法
细嗅蔷薇@1 小时前
迪杰斯特拉(Dijkstra)算法
数据结构·算法
追求源于热爱!1 小时前
记5(一元逻辑回归+线性分类器+多元逻辑回归
算法·机器学习·逻辑回归
ElseWhereR1 小时前
C++ 写一个简单的加减法计算器
开发语言·c++·算法
Smark.2 小时前
Gurobi基础语法之 addConstr, addConstrs, addQConstr, addMQConstr
算法
*TQK*2 小时前
ZZNUOJ(C/C++)基础练习1031——1040(详解版)
c语言·c++·编程知识点