C++详解:关于指针(1)

定义:

指针是一个变量,它储存着另一个的变量的地址(在计算机中储存的位置)。

符号:

  • &:一元运算符,后面紧跟一个变量名,会返回该变量的地址。

  • *:一元运算符,后面紧跟一个(指针中保存的)地址,会返回该地址指向的值。

  • ->:指针成员访问修饰符,当一个指向类/结构体的指针需要访问所指向对象的成员时,需要使用该符号,其中:

class Myclass{
    private:
        int a;
        ...
};
Myclass ptr;
ptr->a

        相当于:

(*ptr).a

多重指针 --- 指向指针的指针:

        我们知道,指针也是一个数据,因此,它也会有自己对应的地址,那么,我们就可以定义另一个指针b,让该指针指向(指向x的)指针a:

int x=12345;

int*  a = &x;    //定义指针a指向x
int** b = &a;    //定义指针b指向a

此时,如果我们想通过b访问x:

std::cout    << x   << endl
             << *a  << endl
             << **b << endl;

结果:

12345
12345
12345

这对于初学者可能有些费解,我们不妨这么想,将int*看作另一种数据类型:

#typedef int * INTPTR

int x=12345;
INTPTR  a = &x;
INTPTR* b = &a;

这样就容易理解了。

以此,我们实际上可以无限套娃下去(然而没有什么实际的用途):

int floor_=1234567890;
int*          ptr1  = &floor_;
int**         ptr2  = &ptr1;
int***        ptr3  = &ptr2;
int****       ptr4  = &ptr3;
int*****      ptr5  = &ptr4;
int******     ptr6  = &ptr5;
int*******    ptr7  = &ptr6;
int********   ptr8  = &ptr7;
int*********  ptr9  = &ptr8;
int********** ptr10 = &ptr9;
std::cout<< floor_ << endl 
        << *ptr1 << endl 
        << **ptr2 << endl 
        << ***ptr3 << endl 
        << ****ptr4 << endl 
        << *****ptr5 << endl 
        << ******ptr6 << endl 
        << *******ptr7 << endl 
        << ********ptr8 << endl 
        << *********ptr9 << endl 
        << **********ptr10 << endl ;
        

(结果就不用写了吧)

NULL指针:

  1. 在VS中,输入NULL,我们可以看到弹出的关于宏NULL的定义:
    #define NULL 0

    所以,NULL的实际值就是0

  2. 使用:在声明一个指针时,我们可能暂时不知道将它赋予何值,那么就可以这么做:
    int* a=NULL;

  3. 意义:在大多数的操作系统上,程序不允许访问地址为 0 的内存,因为该内存是操作系统保留的。然而,内存地址 0 有特别重要的意义,它表明该指针不指向一个可访问的内存位置。但按照惯例,如果指针包含空值(零值),则假定它不指向任何东西。
  4. 检查:我们可以使用if()判断一个指针是否为空指针:
    int* ptr=NULL;
    
    try{
        if(!ptr){throw"The ptr is NULL!";}
    }catch(const char* err){
        std::cerr<<err;
    }
    
    /*    运行结果:
    The ptr is NULL!
    */
  5. 帮助:如果所有未使用的指针都被赋予空值,同时避免使用空指针,就可以防止误用一个未初始化的指针。很多时候,未初始化的变量存有一些垃圾值,导致程序难以调试。
  6. 关于nullptr:C++11中引入了nullptr标识符。它与NULL有什么不同呢?再次查看NULL的定义:
    #define NULL 0

    我们可以知道,NULL是一个int类型的值。看一看C语言中关于NULL的定义:

    #define NULL ((void*)0)

    在这里,NULL是一个指向void的指针。问题来了,我们一向知道,C++是兼容C的,那么为甚么关于NULL的定义却不同呢?实际上,这与C++的重载机制(关于重载,可查阅重载运算符与重载函数)相关。看下面这段代码:

    void f(int){...}
    void f(char*){...}
    
    f(NULL);

    如果C++让NULL也支持void *的隐式类型转换,这样编译器就不知道应该调用哪一个函数。因此,C++将NULL定义成了(int)0,解决了函数重载的匹配问题,但却引入了另一个问题,还是这段代码:

    void f(int){...}
    void f(char*){...}
    
    f(NULL);//将调用f(int)

    由于NULL是(int)0,程序会调用f(int),但从程序员的角度,NULL表示空指针,应调用f(char*)。这就是为什么要引入nullptr关键字。

  7. nullptr的使用:nullptr关键字用于标识空指针,是std::nullptr_t类型的(constexpr)变量。它可以转换成任何指针类型和bool布尔类型(主要是为了兼容普通指针可以作为条件判断语句的写法),但是不能被转换为整数。

    char *p1 = nullptr;     // 正确
    int  *p2 = nullptr;     // 正确
    bool b = nullptr;       // 正确. if(b)判断为false
    

参考资料: 

        C++中的NULL指针

        C++中的nullptr

        C++中的重载

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值