最近买了本C++之父的《C++程序设计语言》打算重学C++。废话不多说,上正题。

C++中的const

(1)简单的定义一个常量

const int number1=1;
int const number2=1;

 这两句是等同的,都是声明了一个值为1的整型常量。需要注意的是,定义一个常量要同时给之赋值。

const int number3;          //error, uninitialized const number3

 像上述这条语句,是编译不过的。

(2)定义常量指针和指针常量

const  int*   ptr1;
const* int    ptr2;
int    const *ptr3;
int * const ptr4; //error, uninitialized const ptr4

 一共4条语句,包含两个不同的意思,因为const可以修饰指针,也可以修饰指针指向的内容。前三句声明指向常量的指针,简称常量指针。也就是说,ptr1,ptr2,ptr3三个指针都指向常量。最后一句表示ptr4是指针常量,即ptr4不可以修改以指向别的对象。这通常比较不容易分辨,我的方法是看const 和*相对位置,比如const *就是声明指向常量的指针,*const就是声明指针常量。

int * const *ptr5;         //error,uninutialized const ptr5

 毫无疑问,上面这条语句的意思是“指向常量指针的指针常量”。即ptr5不能指向其他内容,且ptr5指向的对象不能被修改。

(3)C++不愧是宇宙最难的语言。看看下面两条语句。

const int number=0;
int* ptr=&number;              //error

普通指针不能被赋值为指向常量。这是因为一旦这样赋值,就意味着下面这条语句可以修改常量。

*ptr=1;

 再看看下面这两条语句。

int number;
const int* ptr=&number;        //ok

 这是合法的,换句话说,常量指针可以指向非‘常量。

(4)上面这些内容和C一样。下面来谈谈和C不一样的,引用。

定义一个引用。

type& object2=object1;

 type可以是任何类型,这样相当于给object1起了一个别名object2,对object2所施加的操作会作用到object1上。这里object1也必须是type类型,并且必须是一个左值。

但是定义一个常量的引用就不同了。

const type& object2=object1;

 object1仍然可以是一个左值,但还可以是一个常量,甚至还可以不是type类型。上面这条语句类似于下面这两条语句。

type temp=type(object1);
const type& object2=temp;

需要注意的是,类似并不表示全等。举个例子:

int number=0;
/*1*/const int& refer=number;                 //refer=0
/*2*/int temp=int(number);
    const int& _refer=temp;
number=1000;                         //refer=1000, _refer=0

 以此推测,当object1与object2类型相同时,此类赋值与普通引用赋值一样(小小的不同是不能改变直接显式改变object2),当两者类型不同时,此类赋值与中间变量赋值一样(通过temp)。

(5)const在函数中的应用

char* strcpy(char* ,const char* );

 当函数参数用const修饰时,表示在这个函数中,此参数不改变,如上。

需要注意的是,因为普通引用没有类型转换机制,所以函数参数最好别为普通引用,避免如下尴尬情况的出现。

void function(int& refer);
void _function(const int& refer);
function(3.14159);         //error
function(3.14159);         //better

 这也正是C++之父的建议。

Be suspicious of non-const reference arguments; if you want the function to modify its arguments, use pointers and value return instead.

                                                ------Bjarne Stroustrup《the C++ programming language》

(6)再来看个奇怪的函数。

class a_class{
    int data1;
    int data2;
public:    
  void _function(){
    //change data1 //normal
  } void function()const{
    //change data1 //illegal
  } };

 const 在函数参数之后,这是啥意思?

众所周知,成员函数有一个隐藏参数, this,代表调用此函数的对象。上面的函数_function相当于:

void _function(a_class *this);

 那么问题来了,this这个参数是隐藏的,如何才能做到让编译器识别并禁止改变此对象呢?即如何做到如下效果:

void _function(const a_class *this);

 直接这样写肯定不行,那能不能如下所示呢?

void _function(const );

编译器会认为这是另外一个参数的修饰(并且会报错因为没有类型!) ,而不是this。

于是解决方法就是:

void _function()const;

 总结一下,上面函数声明的意思就是,禁止在此函数中修改调用此函数的对象的内容。

(7)最后说说'类型转换

要了解const,当然不能不了解C++的类型转换const_cast<datatype>(data)

此类型转换专门用来将const类型的指针或引用转换为非const类型,如下:

int number=1;
const int& refer=number;
int& _refer=const_cast<int&>(refer);
refer=12;                      //error
_refer=12;                     //ok, now refer==12, _refer==12, number==12

 当原本数据类型不是常量时,const_cast可以正常工作。那么,如果原本类型就是常量,那会发生什么,如下:

const int number=1;
const int& refer=number;
int& _refer=const_cast<int&>(refer); //undefined behavior
refer=12;                            //error
_refer=12;                           //ok, now refer==12, _refer==12, number==1 in g++

当声明一个常量时,编译器可能会采取某些形式的内存保护措施以确保其内容不被改变。所以这种情况是未定义的,最好不要这样做。

posted on 2016-01-21 14:58  algchthewor  阅读(119)  评论(0编辑  收藏  举报