您的位置:首页 > 其它

关于const变量的思考

2015-06-12 16:51 246 查看
  在类C语言家族(C++ Java)中普遍存在使用const关键字的传统,尤其是C++用法繁多,这里进行了一些整理。const最为基本的用法是替代#define作为常量定义,其好处有:

1. 避免define直接进行字符串替换导致的歧义

2. 便于编译器进行类型检查

3. 减少常量的存储次数,节约空间

此外,这里还隐含了使用const与使用普通变量相比,无法被修改,防止误操作。

const可以应用于指针,其顺序颇为讲究

int x=0;
const int y=0;            //i是常量,i的值不会被修改

int  *const px=&x;     //指针是常量,所指内容可修改
const int *py=&y;        //所指内容是常量,可以不初始化
const int *const p3=&y; //指针p3是常量,所指内容也是常量
py=&x;                  //合法
*px=100;                 //合法


同理 const_iterator可以保证其指向的内容不被修改

const可以修饰类的成员变量。因为类可以创建多个对象,不同的对象其const成员变量的值可以不同。其初始化只能在类的构造函数的初始化表中进行。

const修饰函数参数,如

A& operator=(const A& a);
void fun0(const A* a );
void fun1(const A& a);


  调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化.形参为const A* a,则不能对指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。

[注意]:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。

当const用于对指针的引用的时候,情况变得十分有趣

char *buf1;
const char* buf2;
const char*& cur1=buf1;
const char*& cur2=buf2;
cur1++;
cur2++;


以上哪些是对的,哪些是错的?

该情况在用于字符串paser时会带来纠结,例如

void parser(const char* cur,char*& out)
{
cur++;
out=cur;
//递归
parser(cur,out);
parser(cur,cur);

}


且不论语义如何,以上代码在语法上是无法通过编译的!!!

const修饰函数返回值,如

const A fun2( );
const A* fun3( );


1.函数的返回值为某个对象时,如果将其声明为const,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const (const A& test = A实例),则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。

2.如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。如:

const char * GetString(void);
const char *str=GetString();
char *str=GetString();  //编译错误


3.函数返回值采用“引用传递”的场合不多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达。如:

class A{
…
A &operate = (const A &other);  //赋值函数
}
A a,b,c;              //a,b,c为A的对象
a=b=c;            //正常
(a=b)=c;          //不正常,但是合法


为了将最后一行变为非法,可将函数声明为const

一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。

  在类的成员函数中,任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。

总结与讨论

  从上面几种用法可以看出,对于逻辑正确的代码,添加或删去const不会影响正常的编译过程。使用const关键字只是会提供更多的语法(类型)信息,便于编译器更广地检查出不正确用法的存在。

  一方面,对于类库的设计这来说,有责任提供尽可能多的错误检查机制减轻使用者的debug负担。但是,要求对于每一个变量、函数都判别其属性,思维量是比较大的;反之,限制过于宽松,或一个函数很复杂而只修改一个成员变量,被迫不能添加const,都失去了检查的意义

  另一方面,const static等关键词提供的限制是非常片面的,远远不能起到库对于用户的指导作用。我希望能够探讨更为一般的面向库使用者的限制机制,能够在核心函数用法或者库执行流方面进行更为一般、灵活的提示和限制作用,最好能与编译器和开发环境相结合。

  此外,我们也应该探讨,这类限制的数量上界应该位于何处。工程过极致,则丧失了robustness,这在软件行业的迭代潮流中是不合适的。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: