【C++学习之路】三、指针

一、指针的重要性

C/C++语言之所以强大,以及其自由性,很大部分体现在其灵活的指针运用上。因此,说指针是C/C++语言的灵魂一点都不为过。通过指针,可以简化一些 C++ 编程任务的执行,还有一些任务,如动态内存分配,没有指针是无法执行的。所以,想要成为一名优秀的 C++ 程序员,学习指针是很有必要的。

二、什么是指针

指针是一个变量,其值为另一个变量的地址,即内存位置的直接地址。就像其他变量或常量一样,您必须在使用指针存储其他变量地址之前,对其进行声明。指针变量声明的一般形式为:

type *var-name;
  • type 是指针的基类型,它必须是一个有效的 C++ 数据类型
  • var-name 是指针变量的名称。

指针是c++中的一个重要概念,可以使我们通过指针间接地访问内存的一种工具,而这样的工具就是一把双刃剑,一面可以实现一些非常优化的程序,另一方面也会导致一些难以调试的错误。

三、指针的基操

对于指针来说,取地址(&)解引用(*) 是最基本也是最重要的两个操作符。

1.取地址(&):

每一个变量都有一个内存位置,每一个内存位置都定义了可使用连字号(&)运算符访问的地址,它表示了在内存中的一个地址:

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main()
{
    int  a = 10;
 
    cout << "变量a在内存中的地址: ";
    cout << &a<< endl;
        
    system("pause");
    return 0;
}

执行结果:

变量a在内存中的地址: 0x62fe1c

可以看到,它输出了定义的变量的地址,也就是内容为10int变量a内存中的地址为0x62fe1c

2.解引用(*)

接下来我们看看解引用的使用:

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main()
{
    int  a= 10;
    int  *p;        // 指针变量的声明  
    p = &a;       // 在指针变量中存储 a 的地址 

    cout << "变量a在内存中的地址: ";
    cout << &a<< endl;

    cout << "指针p的值: ";
    cout << p << endl;
   
    cout << "对p解引用获得的值: ";
    cout << *p << endl;
        
    system("pause");
    return 0;

}

执行结果:

变量a在内存中的地址: 0x62fe14
指针p的值: 0x62fe14
对p解引用获得的值: 10

可以看到指针p就是将对应变量在内存中的地址存起来,
对指针解引用就是将指针存的(指向的)地址中的值再给取出来。

那到这的话,可能有人会说那我们为什么要用指针啊,直接通过变量名去访问不就行了?
是可以通过变量名去访问的,因为这里只是演示下指针的基本的操作,在实际中,指针也不会只是对变量进行访问这么朴实,它的存在还是有其他作用的。

四、为什么要使用指针

1.函数传参:

如果一个函数要使用参数,则必须声明接受参数值的变量。这些变量称为函数的形式参数。形式参数就像函数内的其他局部变量,在进入函数时被创建,退出函数时被销毁。
接下来我们直接看一个例子:

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main(){
    int a;
    a = 10;
    test(a);

    cout << "test后a的值为:";
    cout << a << endl;

    system("pause");
    return 0;
}

void test(int a){//形参a
    a = a + 1;
}

执行结果:

test后a的值为:10

在该程序中,我们希望通过test()函数变量a加1输出的值应该为11才对,可是实际输出的却是10。这是因为这种向函数传递参数的方式叫传值调用。 该方法把参数的实际值赋值给函数的形式参数。在这种情况下,修改函数内的形式参数对实际参数没有影响。

就像上面说的,形参a只有在进入test()函数时才被创建出来,它就是一个值与实参相同的另一个变量罢了,对它的操作并不会影响到实参,而当函数结束时,它就会被销毁了,实参是不会有变化的。

那么如何在函数中对实参进行操作呢,这时我们的指针就能派上用场了。我们可以采用指针调用。 该方法把参数的地址赋值给形式参数。在函数内,该地址用于访问调用中要用到的实际参数。这意味着,修改形式参数会影响实际参数。来看例子:

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main(){
    int a;
    a = 10;
    test(&a);//将变量a的地址传进函数

    cout << "test后a的值为:";
    cout << a << endl;

    system("pause");
    return 0;
}

void test(int *a){
    *a = *a + 1;
}

执行结果:

test后a的值为:11

可以看到,当我们通过指针调用进行传参时,在函数内就能对实参进行操作了。这是因为,我们传参时,不像传值调用一样只将值传给形参,而是将实参在内存中的地址信息传给了函数中的指针变量,那我们不仅可以通过对这个指针进行解引用得到实参的值,我们还能通过指针对实参进行修改

不是所有函数都必须要使用指针调用,需根据函数的用途来决定传参的方式

2.数组的遍历

在c++中指针和数组是密切相关的。

原因之一是数组与指针有一个很重要的关系:数组名就是指向数组首元素的指针。(数组的首元素的地址,也被称为数组的基地址):

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main(){
    int arr[] = {1,2,3};

    cout << arr << endl;
    cout << *arr << endl;

    system("pause");
    return 0;
}

执行结果:

0x61fe14
1

另一个原因是指针算数运算自身的一个特点:

指针可以像整形那样进行一部分算数操作,但操作后的指针不一定会指向具有有效数据的地址,所以在进行指针算数操作的时候需要格外小心。

指针可以加上或减去一个整数。 指针的这种运算的意义和通常的数值的加减运算的意义是不一样的,指针的运算是有单位的:

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main(){
    int a = 1;
    int* p = &a;
    
    cout << "p的地址:";
    cout << p << endl;

    p++;
    cout << "p++后的地址:";
    cout << p << endl;

    system("pause");
    return 0;
}

执行结果:

p的地址:0x61fe14
p++后的地址:0x61fe18

可以看到进行p++后,p的地址不是单纯的加1,而是增加了(0x61fe18 - 0x61fe14) = 4,这是因为指针p的类型是int*,它指向的类型是int,对p++,编译之后乘上了它的单位sizeof(int)。

有了这两个原因,我们对于数组的遍历就显得很舒服了:

#include <bits/stdc++.h>//万能头文件
using namespace std;

int main(){
    int arr[5] = {1,2,3,4,5};
    int* p = arr;

    for(int i = 0; i < 5; i++){
        cout << *p << " ";
        p++;
    }

    system("pause");
    return 0;
}

执行结果:

1 2 3 4 5  

这里还有一个需要注意的地方:数组名不能直接自加,即不可对arr++,因为数组被创建出来的时候,它在内存的地址就已经确定下来了,我们不能人为的更改它的位置。但是可以将其赋值给一个指针,指针可以自加:p++

3.其他

关于为什么要使用指针,其实还有许多原因:链表、二叉树等的构建动态分配内存操作申请的堆内存共享内存数据指针和数组的效率问题等等,大家可以自行了解。
其实是我也不太会,嘿嘿,等我学会了再写

以上内容谨为个人学习过程的记录,欢迎大家一起学习和指正

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

嘎嘎学编程

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值