指向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》

转载于:https://www.cnblogs.com/sven/archive/2010/01/19/1651346.html

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值