四 CONST

<meta content="text/html; charset=utf-8" http-equiv="CONTENT-TYPE"> <meta content="OpenOffice.org 2.2 (Linux)" name="GENERATOR"> <meta content="freebird" name="AUTHOR"> <meta content="20070510;9550000" name="CREATED"> <meta content="root" name="CHANGEDBY"> <meta content="20070717;14010300" name="CHANGED"> <style type="text/css"> <!-- @page { size: 8.5in 11in; margin: 0.79in } H1 { margin-top: 0.24in; margin-bottom: 0.23in; line-height: 200%; page-break-inside: avoid } H1.western { font-family: "Liberation Serif", serif; font-size: 22pt } H1.cjk { font-family: "DejaVu Sans"; font-size: 22pt } H1.ctl { font-family: "DejaVu Sans"; font-size: 22pt } P { margin-bottom: 0.08in } --> </style>

const

作为一个基本知识点,要理解const char * const p的含义。第一个const代表p所指向的存储区域是常量,当初始化后不可以被修改;第二个const代表的是变量p一旦指向了某个存储区域后,它就不可以指向别的区域。

在我的文章里面,经常会看到char const* p或者int const a这种用法。他们等价于const char* p和const int a。

const char* p和 char const* p都代表p指向的内存区域是常量,const都是修饰char类型的,但是显然后者更明显。我们应该把const看成是对前面类型的修饰,这样const将char和*p很自然的分隔开来。

char * const p中,const修饰char*类型,代表该指针是不可变的常量指针。

你不觉得这种做法和修饰函数的做法一样么?你肯定见过void A::f() const的用法。

在typedef的使用中,后置const的用法不会产生感觉上的混乱,比如:

typedef char* CHARS;

typedef const CHARS CPTR;//指向char类型的常量指针,不要觉得奇怪,事实就是这样。来看下面的例子:


typedef char* CHARS;

typedef const CHARS CPTR;


int _tmain(int argc, _TCHAR* argv[])

{

CPTR p="a";

p="b";

return 0;

}

error C3892: 'p' : you cannot assign to a variable that is const

有一天,我们忽然用CHARS的等价形式修改了第二句话

typedef const char* CPTR;


typedef char* CHARS;

typedef const char* CPTR;


int _tmain(int argc, _TCHAR* argv[])

{

CPTR p="a";

p="b";

return 0;

}

正确。问题出在typedef const char* CPTR;typedef const CHARS CPTR;居然不等价。当你用后置const来表示,混乱就消失了。

typedef char* CHARS;

typedef CHARS const CPTR;


int _tmain(int argc, _TCHAR* argv[])

{

CPTR p="a";

p="b";

return 0;

}

和下面的

typedef char* CHARS;

typedef char* const CPTR;


int _tmain(int argc, _TCHAR* argv[])

{

CPTR p="a";

p="b";

return 0;

}

都会报同样的错误,error C3892: 'p' : you cannot assign to a variable that is const

我们应该习惯多用const,并且知道何时不该滥用。

1)如果一个类的成员函数不会修改内部数据,用const修饰这是一种提醒,并且也会带来方便。比如下面的代码中,如果你不加const修饰函数,就会遇到麻烦:

class A

{

public:

void f()

{}

};


void Sample(A const& a)

{

a.f();

}



int _tmain(int argc, _TCHAR* argv[])

{

A a;

Sample(a);

return 0;

}

error C2662: 'A::f' : cannot convert 'this' pointer from 'const A' to 'A &'

而像Sample这样的函数你有很大的几率遇到。

2)我们也有可能写Sample这样的函数,当我们的参数是值传递时,不要用const,因为这不会带来好处,还会带来误导,当我们的参数是引用或者指针时,使用const修饰,明确告诉用户传址以提高效率,但是决不会在函数内部修改。

3)如果你不想让别人对你的函数返回值作修改,给它一个const修饰符也不错

4)哲学上,const可以被理解为物理常量和逻辑常量,当一个成员函数被修饰为const,物理常量的理解认为该函数内部绝不可以修改类的成员,逻辑常量理论认为,出于优化的目的,你可以悄悄地修改某个变量,只要不让客户感觉到就可以。我站在逻辑常量这一边。如果你想要在一个const成员函数内修改某个变量,你需要为这个变量加上一个修饰符mutable。比如:


class A

{

public:

void f() const

{

_f=2;

}


private:

mutable int _f;

};


int _tmain(int argc, _TCHAR* argv[])

{

A a;

a.f();

return 0;

}


  1. 我们有时候需要进行const相关的类型转换

从非const引用(或者指针)到const引用是自动完成的。例如:

char* p="f";

char const* p2=p;

反过来去掉const约束的时候,你需要const_cast转换符

char const* p="f";

char* p2=const_cast<char*>(p);

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值