您的位置:首页 > 编程语言 > C语言/C++

小白 有关c++ const的一点总结

2015-04-22 20:34 176 查看
本人学习程序设计已经快有一年之久,c++也有一个多月了,一直觉得c++中的const很令人蛋疼,于是在写程序时就有意的去避免const的使用,近期在写课程设计时却经常出现关于const的bug,于是就逛论坛决心弄懂const,论坛里说的很乱,于是自己做了一点点总结,本人小白,下面的东西仅供参考!有错,欢迎指出。本人使用vc 6.0编译器

一.const的用法

首先来看下面的几个例子

Const char* a

Char const* a

Char *const a

Typedef char*pchar const pchar a

如果都能很准确的说出指针的const类型说明你已经很厉害啦

下面给出解释

第一、二个指针相同,a是一个指向const对象的指针,其所指的对象为const的类型 ,意思是不能通过*a对元素的指进行修改,但可以用非const对象对指针进行赋值,指针所指向的元素也可以修改。第三个,a为const指针,其所指向的不能更改,在一开始定义时必须为其赋值,其所指向的对象的值可以修改,思考一下第四个是const与typedef的结合使用,是不是感觉它和第一二个很像,那你错了不能把typedef简单的当做文本拓展,其实它和第三个是一样的a为const指针。

二.const的赋值问题

1.元素赋值

定义const常量,必须在定义时就为该常量赋值,一个简单的例子(使用常量为const赋值)

Const int i//error

Const int i=5//ok

其实const不能称为常量,因为const的值是可以变化的,看下面的例子,

For(int j=1;j<5;j++)

Const int i=j;//ok

我也不明白从程序为什么可以运行,但是这就意味着我们可以用一个变量去初始化const常量,通过改变变量的值去修改 const的值,这种程序还是不用的好,因为这样就违反了const存在的初衷 但是i同样符合const的特性,一切视图使用变量名i去修改i的值的行为都会导致编译器报错 例如i=5//error 当然也可以使用const常量去初始化一个变量的值

其实这个涉及一个赋值时的对象复制问题,其实想想也是合理的,就不去深究啦!记住就好

2.指针引用赋值

Const最常用到的地方应该是指针和引用,指针和引用也存在不一样的地方,因为指针分为const指针和指向const对象的指针,而引用也就只用指向const对象的引用

首先说两者不一样的 const指针指的是const类型的指针,其指向不能改变,需要定义时赋值,一开始指向谁就以后就一直指向谁不能改变,可是其所指的对象的值却可以改变。例如

Const int* iptr//error

Const int*iptr=&a//ok;

*iptr=5;//ok

iptr=&b//error

而指向const类型对象的指针,其所指向可以改变,却不可以通过*iptr对对象的值进行改变,在定义时不必向上面那样对其赋值 可以在需要使用的时候在对它赋值。举个例子

Const int*iptr//ok;

iptr=&a;//ok

iptr=&b;//ok

*iptr=5//error;

也就是*iptr不能用作左值

有关引用就比指针更严格,定义const引用时,必须对该引用赋值,并且其引用的对象不能改变,这个没什么说的,可是在函数中const引用却用的最多

3.用const对象赋值其他类型的对象

说了那么多都在说对const对象的赋值,上面总结成一句话 const所定义的对象,除了在定义时,其他任何地方都不能用作左值(不知道对不对。。。)

下面说说用const对象赋值其他类型

首先用const对象赋值给const对象肯定是没问题的,当然如果是元素赋值,可以将const对象赋值给非const成员,涉及对象赋值,很好理解 如:

int j;

Const int i=5;

j=i;//ok;

而关于指向const对象的指针 这种指针只能赋值给相同类型的指针必须也为const ,与引用相同,不能将const类型的指针和引用赋值给非const类型的指针和引用。此处关于函数参数传递的问题,也就是因为这个我才开始了解const的。

还有const指针,,不说了,头有点晕,真的很绕人,说错了被打就不好了。。可能我理解的方法有问题。。Const指针可以赋值给非const指针,非const指针也可以赋值给const指针(仅限于初始化const指针的时候)。和元素赋值是一样的。

三.Const在函数中的应用

1.const用在函数前面,如

const int f1(void)

Const A f2(void)

Const A& f3(A&)

Const int*f4(void)

意思是函数的返回值是const,而第一种并不常见,因为系统定义的数据类型int本身返回的就是一个值,不可能是一个变量,用const修饰就没有意义。但是第二种,第三种返回值为const对象就可以避免下面的情况出现

f2()=A2;总是感觉出现这种的可能性不大,但是系统中很多这样的例子,比如a*b只能用作右值,当出现a*b=5时就会报错。

返回值虽然是const,但是仍然可以将返回值赋值给非const对象,当然第三个不可以赋值给非const的引用,却可以赋值给非const对象

例如

A a;

A&b;

a=f2()//ok

a=f3()//ok const引用可以赋值给非const对象(赋值是发生复制操作)

b=f3()//error const引用不能赋值给非const引用

对于第四个函数,返回值为一个指向const类型的指针,由于不能将const类型的指针和引用赋值给非const类型的指针和引用。故左值必须是指向const类型的指针,却又可以把const指针指向的值赋值给非const对象,故有下面的例子

Const int*a//ok

int *b;

Int c;

a=f4()//ok;

b=f4()//error 指向const对象的指针不能赋值给普通指针

c=*f4()//ok const对象可以赋值给非const对象(元素赋值问题)

PS:到目前为止我们很少使用过返回值为引用的函数,更如此很少将函数的返回值定义为const,因为返回的引用所指向的变量必须是全局变量,或者是主函数中使用的,我们可以将赋值=的重载定义为返回值为引用的函数,函数的返回值定义为const的情形多数在重载赋值操作符时出现!!!不到万不得以最好不要使用。

如 A& operator=(const A&a){};可以链式赋值

A a,b,c;

a=b=c;//ok

(a=b)=c//ok 但是不符合链式赋值的标准

此时就可以在函数前面加个const 这样第二种就不合法了。

2.const用在函数形参列表中

const所修饰的形参不可以改变,多数用于引用和指针的时候,为了保证传入的参数不被改变,

例如

Void f1(const int i)

Void f2(const int& i)

Void f3 (const int *i)

对于第一种存在的意义不大,因为本来的i就是传入参数的拷贝,传入参数本来就是安全的,所以不需要const,而第二种第三种就保护了传入的参数不发生改变。

PS:在定义类的成员函数的时候,对于不需要传入的参数发生改变时,一般都在形参前面加一个const,比如重载流操作符,重载关系运算符,默认构造函数。。。

3.Const用在函数体后(类的成员函数)

这种形式一般出现在类的成员函数中,目的是保护类的属性不会发生改变,在函数体内只能调用使用const在后修饰过得函数,一切可能会改变类的属性的函数都不能出现在该函数体内。一般只要在函数内不改变该类的属性的时候,都需要在函数后假如const,增加程序的健壮性

PS:当定义一个对象为const的时候,只能调用该对象的const用在函数体后的函数,

如const A a;

a只能调用此类函数,一切没有用const在后修饰的函数都不能调用

四.下面总结一下赋值问题





Const 对象 非const对象

Const引用 非const引用

Const指针 非const指针

指向const对象的指针 普通指针

“ ”指的是可以赋值

Const在初始化时,对初始化他的值可以是const类型,也可以是非const类型,但是在使用const常量为其他对象的指针和引用赋值时存在限制。

写这篇随笔的初衷:

一开始的我是不愿意涉及const的总觉得他的存在没有那么多的意义,在做程序设计时类的复制构造函数,以及重载等于操作符并没有使用const修饰形参,于是在将类放入vector中时,使用vector容器的push_back时出现了问题

下面贴出push_backde 源码

void push_back(const _Ty& _X)

{insert(end(), _X); }

下面是我遇到的问题:

Vector<R>Rs

Rs.push_back(R);

由于类中定义的复制构造函数传入参数为非const所以会报错

因为参数的传递大概是这样的:

非const对象 const引用 非const引用

后面的传递是传不过来的。

再瞎侃一下:

const有人说在c++中,与c中不相同已经归为常量,但是const与常量该是有很大的不同,毕竟我们可以把一个变量的值赋值给const,通过修改变量的值去修改此const常量的值。

在c++中我们可以定义一个const常量去作为数组的维数,如

Const int n=5;

Int a
;//ok

在c中是不可以的,数组的维数只能使用常量去定义,故此时的const可以认为就是常量

但是如果赋值时是变量 如:

Int j=5;

Const int i=j;//ok

Int a[i]//error C2057: expected constant expression

error C2466: cannot allocate an array of constant size 0

error C2133: 'a' : unknown size

所以在我看啊 const是否为常量应该由其初始化时的值所决定!(仅个人观点)

Const是c++中比较晦涩的部分,看了好久也只略懂一二。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: