c++踩坑大法好 之 指针

1,指针的理解

指针可以理解为一种特殊变量,

一般的变量,如int aa=1;这种,变量储存的是值(也就是1),用地址运算符获取变量在内存中的地址,但是指针不一样,

指针储存的是地址,将接触引用运算符(*,又叫间接值运算符)用于指针,就能拿到该地址处储存的值。

基础实例请看:

#include "pch.h"
using namespace std;
int main() {
    int value = 6;
    int *pvalue;
    //声明一个指针
    pvalue = &value;
    //把value的地址赋值给pvalue指针

    value = 7;
    printf("%d\n", *pvalue);
    //打印出来的数字为7,也就是说value的地址上的值变了,那么指向该地址的指针的取值也会变化。

    *pvalue = 9;
    printf("%d\n", value);
    //打印出来value的值为9,*pvalue=9的意思是,对pvalue所储存的地址的值赋值为9,而这个地址的值所对的变量正事value,所以它也会改,
    return 0;
}

 注意术语:*pvalue是int,pvalue是指向int的指针,

2,星号跟谁走?

跟谁走都可以,这不会报错,但是强调重点不同

int *ptr;
//c风格,强调的是*ptr是int类型
int* ptr;
//强调ptr属于一种复合类型:int*,读为指向int的指针

//注意,注意
int* ptr,hehe;
//这种写法实际上声明了一个指针和一个int,所以个人推荐星号跟着变量名走,防止引发以上错误。

 3,指针传参,引用传参

1,局部变量的值改了,全局变量的值不会改

#include <iostream>

using namespace std;
int test(int xc);
int main() {
    int t2 ;
    t2 = 2;
    test(t2);
    printf("quanju %d\n", t2);//打印为:2
    return 0;
}
int test(int xc) {
    int t1 = 1;
    xc = t1;
    printf("jubu %d\n",xc);
    return 0;
}
//把一个int变量的值传递给函数,函数内部改变了值,函数运行的时候值确实改变了,但是结束以后,外部值没有发生变化

2,引用的值变了,被引用的值也变了。

#include <iostream>

using namespace std;
int test(int &xc);
int main() {
    int t2 ;
    t2 = 2;
    test(t2);
    //此处相当于int &xc=t2;xc这个变量现在是t2的引用,引用的意思就是你变我也变
    printf("quanju %d\n", t2);//打印为:1
    return 0;
}
int test(int &xc) {
    int t1 = 1;
    xc = t1;
    printf("jubu %d\n",xc);
    return 0;
}
//把一个int变量的引用传递给函数,函数内部改变了变量的引用的值,函数运行结束以后,外部值也变了。

3,通过指针修改了被指向的区域的值,全局和局部变量都变了

#include <iostream>

using namespace std;
int test(int *xc);
int main() {
    int t2 ;
    t2 = 2;
    test(&t2);
    //此处相当于int *xc=&t2;int型指针xc这个变量现在指向的是t2的地址,指向的意思是变量前面加上星号就能得到指向的区域的内容
    printf("quanju %d\n", t2);//打印为:1
    return 0;
}
int test(int *xc) {
    int t1 = 1;
    *xc = t1;
    printf("jubu %d\n",*xc);
    return 0;
}
//把一个int变量的地址传递给函数,函数接收为int类型的指针,内部改变了指针指向的内存区块的值,函数运行结束以后,外部值也变了。

4,仅仅是在局部把指针的指向变了,局部变量确实变了,但是全局变量没有改变

#include <iostream>

using namespace std;
int test(int *xc);
int main() {
    int t2 ;
    t2 = 2;
    test(&t2);
    //此处相当于int *xc=&t2;int型指针xc这个变量现在指向的是t2的地址,指向的意思是变量前面加上星号就能得到指向的区域的内容
    printf("quanju %d\n", t2);//打印为:2
    return 0;
}
int test(int *xc) {
    int t1 = 1;
    xc = &t1;
    //xc是个地址,*xc是个值,通过修改xc的地址,改了xc的指向(原本指向t2,现在指向t1)
    printf("jubu %d\n",*xc);
    return 0;
}
//把一个int变量的地址传递给函数,函数接收为int指针,局部修改了指针的指向,并没有影响到全局变量。

 

4,使用new来创建指针

指针普通使用方法如下:

int a=1;
//创建一个内存空间,名字叫a,内部存储的是int类型,1
int *ptr=&a;
//创建一个int型指针,指向a的地址。

//现在对于变量a和其中储存的1来说,除了变量本身能够访问这个有名称的内存外,ptr也可以访问。

1),使用new为指针分配内存空间:

int *ptr=new int;
//创建int型指针ptr,并且为该指针分配一个int大小的内存空间。
*ptr=2;
//把2这个值存储到指针指向的内存中去。

//new方法和普通方法的区别在于,普通指针指向一个变量,变量有名称有值有内存空间,而new方法指向的是一个数据对象,它没有名称有值有内存空间,除了指针以外,不能被访问,另外,ptr的值在栈中,而new会从堆的内存区分配。

2),使用new的指针需要自行释放内存空间------使用delete:

int *ptr=new int;
delete ptr;
//new出来的指针使用完毕后记得释放,即使是释放空指针也没问题,但是不能多次执行delete释放同一个变量,也不能释放非new创建的指针
int *pt=new int[500];
//new去创建一个包含500元素的int数组,然后把第一个元素的指针赋值给pt
delete [] pt;
//如果执行delete pt,系统一看pt是个int型的指针,然后闻着味就仅仅把数组第一个元素释放掉了,只有告诉系统这个是想释放整个数组:delete [] pt才能真正释放掉数组

3),new创建的指针数组如何使用?

#include <iostream>
using namespace std;
int main()
{
    int *pt = new int[10];
    pt[0] = 1;
    pt[1] = 2;
    //既然是指针,按理说pt是个地址,但是c++同时也把它当作一个数组名来使用,所以说以上写法是合法的
    
    printf("first:%d \n", *pt);
    //pt是指向第一个元素的地址,所以打出来是第一个元素的值

    pt = pt + 1;
    printf("second:%d \n", *pt);
    //把pt当成一个地址,对其加一,将指向第二个元素(实际上是加了四个字节,因为是int),这时候打出来的是第二个元素的地址

    pt = pt - 1;
    delete [] pt;
    //在释放以前必须保证pt是指向首元素的
    return 0;
}

 

posted @ 2024-12-05 13:57  0点0度  阅读(31)  评论(0)    收藏  举报