四 CONST

来源:互联网 发布:cad排版软件 编辑:程序博客网 时间:2024/03/29 18:50
 

const

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

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

const char* pchar const* p都代表p指向的内存区域是常量,const都是修饰char类型的,但是显然后者更明显。我们应该把const看成是对前面类型的修饰,这样constchar*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);