C++中的指针和引用(非扫盲博文)

本文详细解析了C++中的指针与引用概念,包括它们的基本用法、数组与指针的关系、作为函数参数时的注意事项及陷阱,强调了引用的安全性和效率优势。

考研过后又重新捡起C++的书本开始学习,很多以往学到的现在却又有所忽略,尤其是C++中指针,引用的问题,这是C++的精妙之处,也是C++难以掌握的一个非常关键的点。
总结得不是很全,这个要是所有的都写上,那花的时间就多了去了,比较适合已经对指针和引用有了一定了解的人看
总结下C++中关于指针和引用的那些事。
指针概念:

int *c;
int a=2;
c=&a;
//指针就是地址,就是指向另外一块内存
——————————————————————————————————————————————————————
int a=2;
int *c=&2;
//这段代码和上面一样,先定义后取地址
______________________________________________________
由于指针指的是地址,所以就可以间接操作变量a
*c=3;
这样a的值也就变成了3

引用概念:

引用就简单了,就是取了另外一个名字而已
int a=0;
int &b=a;
然后对b的操作其实也是对a的操作
比如:
b=3;
这样a也变成3

引用变量就是一个别名!只是给原事物换了个包装壳用了另外一个名字而已!!!记住这句话,引用的问题就差不多解决了!!!

指针和数组
(这个就有得说了,其中坑也有很多,可我觉得掌握核心要点就好了,如果别人代码风格比较奇葩就把它改过来)

**一维数组**
int a[4]={1,2,3,4,5};
int *c;
c=a;
这样就可以用指针c去操作数组a
a[2]=*(c+2);
其实a[2]这样的写法在编译器处理的时候也是处理成*(c+2);只是做个语法糖方便使用,增加可读性
**二维数组**
<font face="黑体">
int a[4][4]={{1,2,3,4},{1,2,3,4},{1,2,3,4},{1,2,3,4}};
int *c[4];
for(int i=0;i<4;i++)
c[i]=a[i];
----------------------------------------------------------
a[2][2]=*(*(a+2)+2)=*(a[2]+2)三者相等
c[2][2]=*(*(c+2)+2)=*(c[2]+2)三者相等
他们指的东西是相同的
</font>

这些都是比较基础的指针用法,关于二维数组有一个很容易搞混的地方

int a[2][2] = { {1,2},{3,4} };
这个代码中
sizeof(a)值是16
sizeof(a[0])是8
sizeof(a[0][0])是4
因为a指的是整个数组
a[0]就是指第0行
a[0][0]就是指第一个元素

关于指针还有一个很重要的点!就是当函数参数是指针的时候要特别注意
首先:不要产生野指针,因为野指针是随便指向一块内存块,万一执行了什么操作那就会引发大问题,C++编译器也会有预防野指针乱用的方法,比如

#include<iostream>
using namespace std;
void canshu(char*f)
{
    f = new char;
    *f = 'a';
}
int main()
{

    char *s;
    canshu(s);
    cout << *s << endl;
    getchar();
    return 0;
}
编译器会报错,但是把s初始化后可以看下
#include<iostream>
using namespace std;
void canshu(char*f)
{
    f = new char;
    *f = 'a';
}
int main()
{
    char code='b';
    char *s=&b;
    canshu(s);
    cout << *s << endl;
    getchar();
    return 0;
}
但是输出s仍然还是b

所以在很多时候,当我们把指针作为实参,并且想将该指针在另外一个函数中给它分配一块内存,我们通常都是这么做
(首先我们先来点难度小一点的)
在函数体中改变字符变量的值
方法一:指针法间接操作

void canshu(char*f)
{
    *f = 'q';
}
int main()
{
    char c='w';
    char *s = &c;
    canshu(s);
    cout << *s << endl;
    getchar();
    return 0;
}

方法二:引用法直接更改

void canshu(char &f)
{
    f = 'q';
}
int main()
{
    char c = 'b';
    canshu(c);
    cout << c<< endl;
    getchar();
    return 0;
}

两道小菜消化消化,离成功就进了一步!

那就回到最初始的题目:
如何在函数体中给传进来的指针实参分配内存呢?????
1)将形参声明为指针引用

void canshu(char*&f)
{
    f = new char;
    *f = 'a';
}

为什么这样就可以了呢?
因为这就是引用的特性!一个变量是引用的就说明给它什么,它用的就是什么,而不会再复制出一个临时变量出来!
引用变量就是一个别名!只是给原事物换了个包装壳用了另外一个名字而已!!!记住这句话,引用的问题就差不多解决了!!!
2)采用双指针
先提一下,之前已经说过了,指针就是地址,指向另一个变量所在的地址,通过它可以间接地去访问其他变量,我们这里也可以采用这个方法去控制

void canshu(char**f)
{
    *f = new char;
    **f = 'a';
}
int main()
{
    char c = 'b';
    char *s = &c;
    canshu(&s);//注意区分,这里的'&'符号的作用是取地址
    cout << *s << endl;
    getchar();
    return 0;
}

这种已经是难度比较高,比较难理解的问题了.掌握了上面指针的问题,掌握了上面所有的指针用法,引用含义,对指针的使用应该是一般都可以应付了,但是C++奥妙无穷,还有很多很多坑需要去慢慢发掘。

上述两个要点是非常非常重要的点,指针有关函数参数的问题还有一个要点

void canshu(char*f)
{
    int x=sizeof(f);
    //无论传进来的f值有多大,x的值都是类型的大小值
    char变量为1字节,那么就是1
    int变量是4字节,那么就是4
    double8个字节,那么就是8
    (这个和电脑,编译器有关,我是windows10/visual studio下测试)
}

所以当我们传递数组,字符串时,取sizeof来得到容量大小是得不到的,还是要另外声明一个大小做参数比较好,我觉得这样的函数设置比较安全。

关于引用的一个陷阱:对全局变量进行引用,这样会出编译器错误
上述例子可以见得,指针和引用有时候可以相互取代,用哪个更好??
答案是能用引用就用引用
一:引用更安全,引用被赋值以后就不能被更改,而指针可以更改指向不同对象(当然你需要用到这个性质的话就使用指针)
二:指针可能产生野指针,而这一点非常致命,容易导致严重的bug,而引用不会有这种问题。正因为指针可以指向对象,可以空值(野指针),可以null,所以需要进行测试,这样相比,引用的效率就高写了
三:引用创建的时候必须初始化
总之,指针比引用灵活,引用比指针高效安全,各取所长,就能开发出又灵活多变又安全高效的代码,这就是C++的魅力之处啊,管中窥豹不外如是!
指针的用途十分广泛,其实用的比引用多些
把握这几个点,对于指针的使用会越来越熟练
一:指针移动的时候要先看看指针每次移动多少,这和它类型有关
二:指针赋值的时候看看类型是否匹配
三:指针做函数参数的时候看看你是不是想给传进来的实参分配内存?
四:处处防止出现野指针,指针不用请赋值为NULL;
感觉几个最关键的,最容易搞不懂的点都总结了,还有些指针数组和数组指针,函数指针和指针函数,常量引用和引用常量等等等等,先挂几个链接,以后有遇到比较容易搞错的坑再补一下吧
指针数组和数组指针
指针函数和函数指针
(这个最常见的就是C++ algorithm库中的sort函数第三个参数了,sort函数默认是递增,但是改变排序方向就要编写一个函数作为参数传递进去,本质就是用的函数指针)
常量引用和引用常量

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值