C++学习笔记:指针相关

1.引用和指针

实际是一个变量的别名,类型 &来声明

与指针的不同

1、并且不能为NULL,且一定要初始化,不能改变;指针可以为NULL,且可以指向不同的对象

2、不能有多级引用;指针可以有多级

3、++ 和 -- 操作,指针是对地址,引用是对引用的变量操作;引用访问时直接访问,而指针访问时间接访问

code:

#include<iostream>
using namespace std;

void swap1(int &a, int &b){
    int t = a;
    a = b;
    b = t;
}

void swap2(int* a, int* b){
    int temp = *a;
    *a = *b;
    *b = temp;
}
int main(){
    int x=1, y=2;
    int* p1=&x,* p2=&y;
    cout<<x<<y<<endl;
    swap1(x,y);
    cout<<x<<y<<endl;
    swap2(p1,p2);
    cout<<x<<y<<endl;
    return 0;
}

结果:12  21  12

 

可见都实现了交换

引用和指针的意义用一张自己做的图帮助理解,但是内存中显然不是这样的。

  

引用就像变量名一样绑在content后面,使得该引用不能再指向别的content,当然一个变量可以有很多个引用;指针则是另外的变量,存储了content所在的内存地址,

在swap函数中,指针是通过&地址的方式间接改变content的值;引用则是直接改变。

 

2.指向常量的指针

就是一种只读的指针,能通过指针访问指向的值,但不能通过指针改变指向的值;并且可以改变指针指向的地址。

#include<iostream>
using namespace std;

int main(){
    int a=1,b=2;
    const int *p = &a;
    cout<<*p;
    //*p = 3;试图改变a的值,报错
    p = &b;//可以改变指针的指向
    return 0;
}

 

3.指针数组

定义:int *p[3],表示的是一个有三个int类型指针的数组(本质是一个数组),其中p[1],p[2],p[0],都是指针,p是数组名

#include <iostream>
using namespace std;

int main(){
    int line1[]={1,0,0};
    int line2[]={0,1,0};
    int line3[]={0,0,1,1};

    int *pLine[3] = {line1,line2,line3};
    cout<<"matrix:"<<endl;
    for(int i=0; i<3; i++){
        for(int j=0; j<3; j++){
            cout<<pLine[i][j]<<' ';
        }
        cout<<endl;
    }
    return 0;
}

 

结果:可以看到,指针数组可以当作二维数组去使用。因为指针数组中存放的是地址,但是比二维数组更为灵活(实现方式更像链表),可以每个长度不一样。

matrix:
1 0 0
0 1 0
0 0 1

PS:区别与数组指针,数组指针是一个指向数组的指针变量。如:int (*p)[2]  表示的是:一个指向含有两个int的数组的指针,对p指针的+1操作也是一个数组为单位。

#include <iostream>
using namespace std;
int main(){
    int a[2][2]= {1,2,3,4};
    int (*p)[2]=a;
    cout<<*(*p+1)<<' '<<**(p+1);
    return 0;
}

输出为: 2  3

相信应该理解了数组指针了。

 

4.指针类型函数

即返回值为一个地址的函数

注意:不要把非静态局部变量的地址返回,因为在函数结束的时候,非静态地址会被释放

#include <iostream>
using namespace std;

int* func(){
    int local=0;//非静态局部变量在函数结束时,已被释放,返回的地址已经不是原来的local值
    return &local;
}

int main(){
    int* p;
    p = func();//如果对p指针再赋值的话,将是非常危险的操作
    return 0;
}

正确1:

#include <iostream>
using namespace std;

int* func(int* a, int num){
    for(int i=0; i<num; i++){
        if(a[i]==0)
            return &a[i];//在数组内部找,返回的地址任然是在main函数中有意义的地址,而不是野指针
    }
}

int main(){
    int arr[10]={1,2,3,4,5,6,7,8,9,0};
    int *p = func(arr, 10);//数组arr地址传给func
    cout<<*p;
    return 0;
}

正确2:用new分配内存空间,用delete释放内存

#include <iostream>
using namespace std;

int* func(){
    return new int();//new一个int类型的内存地址
}

int main(){
    int *p = func();
    *p = 5;
    cout<<*p;
    delete p; //释放new出的内存地址
    return 0;
}

5.指向函数的指针(函数指针)

实现函数回调,多个不同功能的函数的接口一致(但参数类型、个数和返回类型要一样)

#include <iostream>
using namespace std;
//告诉compute函数,这有个func函数的地址可以使用,用*func可以找到,且func的参数一定是int,int,
//返回值也是int。
int compute(int a,int b,int(*func)(int, int)){
    return func(a, b);//new一个int类型的地址
}

int max1(int a,int b){
    return (a>b)?a:b;
}

int min1(int a,int b){
    return (a<b)?a:b;
}

int sum1(int a,int b){
    return a+b;
}

int main(){
    int res,a=2,b=4;
    res = compute(a,b,&max1);//在compute调用时,对函数名取地址,告诉程序这个func函数地址在哪
    cout<<"max:"<<res<<endl;
    res = compute(a,b,sum1);//函数名和&函数名一样都是表示函数的地址
    cout<<"sum:"<<res<<endl;
    return 0;
}

要与函数重载区分开(实现的是相同功能的同一接口,如都是求和的int和float之分)

有关函数重载的在我的另一个笔记里:https://blog.csdn.net/Wzz_Liu/article/details/81808893

 

6.this指针

实际上,我们新建一个对象,这个对象调用成员函数时,编译器自动将该对象的地址赋给this指针,成员函数访问成员变量,默认使用了this,this指针就是当前对象所在的地址。

比如类中的一个成员函数return x;,相当于return this->x;

 

7.对象指针(前向引用所不能解决的问题)

解决之前前向引用所不能解决的,类中的需要实例化另一个未先定义的类的对象

链接:https://blog.csdn.net/Wzz_Liu/article/details/82220552,即第五行B b那一句。

#include<iostream>
using namespace std;
class B; //前向引用声明
class A{
    B *b;
public:
    void f(B b);
};

class B{
public:
    void g(A a);
};

int main(){
    return 0;
}

编译器无需知道给定多少的空间给一个B类对象,只需要定义一个B类的指针b(大小为一个地址)

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值