[C++]指针

目录

一.概念

二.注意

三.指针值状态

四.指针的使用原理

五.指针的操作

5.1 指针与数组

5.2 指针也是迭代器

六.void* 指针

6.1 概念

6.2 获取void*指针所存地址

七.VS的指针格式

八.指针与引用的复合

九.指针和const

9.1 指向常量的指针

9.2 const指针(常量指针)

9.3 指向常量的指针和指针常量的区别


一.概念

        指针是“指向”另外一种类型的复合类型,实现了对其他对象的间接访问。指针本身就是一个对象,它是有空间的,它允许对指针赋值和拷贝,而且可以先后指向不同的对象。

int *a;
int b=10;
int *o=b;

二.注意

  1. 除两种例外的情况:指向常量的指针、指向基类的指针,其余所有的指针类型都要与它所指向的对象类型相匹配

三.指针值状态

指针的值应该属于下列四种状态之一:

  1. 指向一个对象。
  2. 指向紧邻对象所占空间的下一个位置。
  3. 空指针,意味着指针没有指向任何对象。
  4. 无效指针,也就是上述情况之外的其他值。

四.指针的使用原理

int a=10;
int *P=&a;

        P是一个标识符,这个标识符里通过取地址符(&)存储着a的地址,通过解地址符(*)可以获取地址所存储的值*p。

五.指针的操作

int *val=NULL; //这是c++11以前版本,置指针为空指针的操作,NULL是一个预处理变量,现在已经不推荐使用了
int *val=nullptr; //这是C++11定义的新特性,如今使用的置空指针的操作。
int *val=0; //这个也是置空指针操作
if(val)   //判断val如果为空,则不进行下列语句
/...

5.1 指针与数组

string nums[]={"one","two","three"};
string *p=nums; //实际进行的转换 *p=&nums[0];
string *p=&nums[0];

所以由上可知,对于数组的操作实际上是指针的操作,比如:

  1. auto关键字
int ia[]={0,1,2,3};
auto ia2(ia);  //实际进行操作是 ia2(&ia[0]);
ia2=42; //err,因为ia2现在是一个指向ia数组第一个元素的整型指针,而不能给它赋值42这个字面常量值

     2.decltype关键字(特殊)

decltype(ia) ia3={0,1,2,3};
ia3=p; //err,因为decltype关键字,不会发生&ia[0]的转换
ia3[4]=10; //true

5.2 指针也是迭代器

        迭代器对容器的操作,在指针对数组的操作中也是能做到的,指针也支持使用自增运算符来让指针指向数组的下一个位置的值:

int ok[]={1,2,3};
int *p=ok;
++p; //p指向ok[1];

int *e=&ok[3];  // 获取ok末尾的指针,这个指针指向未知位置,不能取值只能判断
for(int *p=ok;p!=e;++p)  //遍历ok数组
{
    ...
}

六.void* 指针

6.1 概念

        void* 指针是一种特殊的指针类型,可用于存放任意对象、任意类型的地址,但是不能对它进行操作,因为你并不知道它存储的是什么类型的对象。

6.2 获取void*指针所存地址

.......

七.VS的指针格式

        在VS里指默认的指针格式是int* p=0; 因为在C#里是只允许前放的,在《C++ prime》里推荐使用靠后的方式即int *p=0; 这样是为了区分 * 只是一个修饰符,它并不对后面的变量产生影响,即如果这样写int *p,i; 这样这个i只是int类型,而不是向靠前书写一样会造成i是一个int型指针的误解,要在VS里改变这个指针格式也很简单,就在菜单栏—工具—选项—文本编辑器—C/C++—代码样式—格式设置—间距换行—指针/引用对其方式,里修改即可。

八.指针与引用的复合

阅读一下代码

true: 
    int i = 100;
    int *a = &i;
    int **b = &a;
false:
    int ***c = &a; // err,因为这时候**c就存储的是a的地址,*c存储的是i的地址,但c此时存储的却不是地址类型,而是i的值。

true:
    int *&c = a;
    c = &i;
false:
    int *&c=&i; // err,因为这时候c是一个int指针类型的引用,而引用有个要求就是引用绑定的对象类型必须与引用类型相同,而这里引用绑定的类型是一串地址,引用本身的类型却是int指针类型,所以是错误的。
    int &*c=i; // err,因为引用不是一个对象,不能定义一个指向引用类型的指针,因为它没有分配空间,而指针是一个对象是需要空间的,所以不能这样使用。

true:
    *c = 0;  // 此时c是a的别名了,对c的操作就是对a的操作
    cout << *a << endl;

技巧:可以从右往左读,离变量名最近的符号对变量有直接影响,如上面的int *&c=a;从右往左读,先得到c是一个引用类型,然后再得到它是一个int指针类型的引用。

九.指针和const

9.1 指向常量的指针

指向常量的指针不能用于改变其所指对象的值,要想存放常量对象的地址,只能使用指向常量的指针。同时其左右类型不必相同。

    const int a = 10;
    const int *o = &a;
    int b = 10;
    const int *c = &b;

指向常量的指针的变量存储的是对象的地址,但是常量const修饰的是这个int型指针,所以对于这个int型指针的赋值操作不能进行。

    int b = 10;
    const int *c = &b;
    b = 20;
    cout << *c << endl; // *c=20;

9.2 const指针(常量指针)

把指针本身定为常量。即:

int a=10;
int *const p=&a;

注意:

  1. 常量指针必须初始化,而且一旦初始化完成,将不可改变
  2. 常量指针存储的是指向对象的地址常量const修饰的是这个变量,而这个变量存储的是地址,所以地址是不能改变的,不过也意味着,这个地址指向的对象的值是可以改变的。

9.3 指向常量的指针和指针常量的区别

1.指向常量的指针和指针常量都可以间接的改变所指向对象的值。

    int b = 10;
    const int *c = &b; // *c=10;
    b = 20;
    cout << *c<< endl; // *c=20;

    int *const d = &b; //*d=20;
    b = 30;
    cout << *d << endl; // *d=30

2.指向常量的指针可以修改其所指向的对象,常量指针不能指向其所指向的对象。

    int b = 10;
    const int *c = &b;
    int k = 20;
    c = &k;  // true, 修改c所指向的对象

    int *const d = &b;
    int h = 40;
    d = &h;  // err,不能修改d所指向的对象

3.指向常量的指针不能通过指针来修改所指向对象的值,常量指针可以通过指针来修改所指向对象的值。

    int b = 10;
    const int *c = &b;
    *c = 20; // err,指向常量的指针不能通过指针来修改对象的值
    cout << *c<< endl;

    int *const d = &b;
    *d = 20;  //true,常量指针可以通过指针来修改对象的值
    cout << *d << endl;

综上,指向常量的指针和指针常量之间的区别主要是看const修饰的内容,const修饰的什么内容,那么这个内容就不能修改。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值