zoukankan      html  css  js  c++  java
  • 指向const对象的指针

      指向const对象的指针

      到目前为止,我們使用指针来修改其所指对象的值。但是如果指针指向const对象,则不允许用指针来改变其所指的const值。为了保证这个特性,C++语言强烈要求指向const对象的指针也必须具有const特性。

    //这里的cptr是一个指向double类型const对象的指针,const限定了cptr指针所指向的对象类型,而并非cptr本身。也就是说,cptr本身并不是const。在定义时不需要对它进行初始化,如果需要的话,允许给cptr重新赋值,使其指向另一个const对象。但不能通过cptr修改其所指对象的值。
    const double *cptr; //cptr may point to a double that is const
    //以下定义是错误的
    *cptr=42;

      把一个const对象的地址赋给一个普通的,非const对象的指针也会导致编译时错误:

    const double pi=3.14;
    double *ptr=π //error: ptr is a plain pointer
    const double *cptr=π //ok: cptr is a pointer to const
    

      不能使用void*指针保存const对象的地址,而必须使用const void*类型的指针保存const对象的地址:

    const int universe=42;
    const void *cpv=&universe; //ok: cpv is const
    void *pv=&universe; //error: universe is const
    

      允许把非const对象的地址赋给指向const对象的指针,例如:

    double dval=3.14; //dval is a double, its value can be changed
    cptr=&dval; //ok: but can't change dval through cptr
    

      尽管dval不是const对象,但任何企图通过指针cptr修改其值的行为都会导致编译时错误。cptr一经定义,就不允许修改其所指对象的值。如果该指针恰好指向非const对象时,同样必须遵循这个规则。注:不能使用指向const对象的指针修改基础对象,然而如果该指针指向的是一个非const对象,可用其他方法修改其所指的对象。

      事实是,可以修改const指针所指向的值,这一点常常容易引起误会。考虑:

    dval=3.14159; //dval is not const
    *cptr=3.14159; //error: cptr is a pointer to const;
    double *ptr=&dval; //ok: ptr points at non-const double
    *ptr=2.72; //ok: ptr is plain pointer
    cout<<*cptr; //ok: prints 2.72
    

      在此例中,指向const的指针cptr实际上指向了一个非const对象。尽管它所指的对象并非const,但仍不能使用cptr修改该对象的值。本质上来说,由于没有方法分辨cptr所指的对象是否为const,系统会把它所指的所有对象都视为const。

      如果指向const的指针所指的对象并非const,则可直接给该对象赋值或间接利用普通的非const指针修改其值:毕竟这个值不是const。重要的是要记住:不能保证指向const的指针所指对象的值一定不可修改。

      在实际的程序中,指向const的指针常用作函数的形参。将形参定义为指向const的指针,以此确保传递给函数的实际对象在函数中不因为形参而被修改。

      const指针

      除指向const对象的指针外,C++还提供了const指针---本身的值不能修改:

    int errNumb=0;
    int *const curErr=&errNumb; //curErr is a constant pointer
    

      我們可以从右向左把上述定义语句读作“curErr是指向int型对象的const指针”。与其他const量一样,const指针的值不能修改,这就意味着不能使curErr指向其他对象。任何企图给const指针赋值的行为(即使给curErr赋同样的值)都会导致编译时错误:

    curErr=curErr; //error: curErr is const
    

      与任何const量一样,const指针也必须在定义时初始化。

      指针本身是const的事实并没有说明是否能够使用该指针修改它所指向对象的值。指针所指对象的值能否修改完全取决于该对象的类型。例如,curErr指向一个普通的非常量int型对象errNumb,则可使用curErr修改该对象的值:

    if(*curErr)
    {    
      errorHandler();
      *curErr=0; //ok: reset value of the object to which curErr is bound
    }
    

      指向const对象的const指针

      还可以如下定义指向const对象的const指针: 

    const double pi=3.14159;
    //pi_ptr is const and points to a const object
    const double *const pi_ptr=π
    //本例中,既不能修改pi_ptr所指向对象的值,也不允许修改该指针的指向(即pi_ptr中存放的地址值)。可从右向左阅读上述声明语句:“pi_ptr首先是一个const指针,指向double类型的const对象”。

      指针和typedef

      在typedef中使用指针往往会带来意外的结果。下面是一个几乎所有人刚开始都会答错的问题。假设给出以下语句:

    typedef string *pstring;
    const pstring cstr;
    

      请问cstr变量是什么类型?简单的回答是const pstring类型的指针。进一步问:const pstring指针所表示的真实类型是什么?很多人都认为真正的类型是:

    const string *cstr; //wrong interpretation of const pstring cstr
    

      也就是说,const pstring是一种指针,指向string类型的const对象,但这是错误的。

      错误的原因在于将typedef当做文本扩展了。声明const pstring时,const修饰的是pstring类型,这是一个指针。因此,该声明语句应该是把cstr定义为指向string类型对象的const指针,这个定义等价于:

    //cstr is a const pointer ro string
    string *const cstr; //equivalent to const pstring cstr
    

      阅读const声明语句产生的部分问题,源于const限定符既可以放在类型前也可以放在类型后:

    string const s1; //s1 and s2 have same type
    const string s2; //they are both strings that are const
    

      用typedef写const类型定义时,const限定符加载类型名前面容易引起对所定义的真正类型的误解:

    string s;
    typedef string cstr1=&s; //written this way the type is obscured
    pstring const cstr2=&s; //all three decreations are the same type
    string *const cstr3=&s; //the are all const pointers to string
    

      把const放在类型pstring之后,然后从右向左阅读该声明语句就会非常清楚的知道cstr2是const pstring类型,即指向string对象的const指针。

      不幸的是,大多数人在阅读C++程序时都习惯看到const放在类型前面。于是为了遵照惯例,只好建议编程时把const放在类型前面。但是,把声明语句重写为置const于类型之后更便于理解。

      以上文字摘自 《 C++ Primer》

  • 相关阅读:
    android29
    android28
    android27
    android26
    Dynamics CRM2011 MspInstallAction failed when installing an Update Rollup
    Dynamics CRM Import Solution Attribute Display Name description is null or empty
    The service cannot be activated because it does not support ASP.NET compatibility
    IIS部署WCF报 无法读取配置节“protocolMapping”,因为它缺少节声明
    Unable to access the IIS metabase.You do not have sufficient privilege
    LM算法与非线性最小二乘问题
  • 原文地址:https://www.cnblogs.com/sven/p/1651346.html
Copyright © 2011-2022 走看看