关于const变量的思考
2015-06-12 16:51
246 查看
在类C语言家族(C++ Java)中普遍存在使用const关键字的传统,尤其是C++用法繁多,这里进行了一些整理。const最为基本的用法是替代#define作为常量定义,其好处有:
1. 避免define直接进行字符串替换导致的歧义
2. 便于编译器进行类型检查
3. 减少常量的存储次数,节约空间
此外,这里还隐含了使用const与使用普通变量相比,无法被修改,防止误操作。
const可以应用于指针,其顺序颇为讲究
同理 const_iterator可以保证其指向的内容不被修改
const可以修饰类的成员变量。因为类可以创建多个对象,不同的对象其const成员变量的值可以不同。其初始化只能在类的构造函数的初始化表中进行。
const修饰函数参数,如
调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化.形参为const A* a,则不能对指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。
[注意]:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。
当const用于对指针的引用的时候,情况变得十分有趣
以上哪些是对的,哪些是错的?
该情况在用于字符串paser时会带来纠结,例如
且不论语义如何,以上代码在语法上是无法通过编译的!!!
const修饰函数返回值,如
1.函数的返回值为某个对象时,如果将其声明为const,多用于操作符的重载。通常,不建议用const修饰函数的返回值类型为某个对象或对某个对象引用的情况。原因如下:如果返回值为某个对象为const(const A test = A 实例)或某个对象的引用为const (const A& test = A实例),则返回值具有const属性,则返回实例只能访问类A中的公有(保护)数据成员和const成员函数,并且不允许对其进行赋值操作,这在一般情况下很少用到。
2.如果给采用“指针传递”方式的函数返回值加const修饰,那么函数返回值(即指针)的内容不能被修改,该返回值只能被赋给加const 修饰的同类型指针。如:
3.函数返回值采用“引用传递”的场合不多,这种方式一般只出现在类的赋值函数中,目的是为了实现链式表达。如:
为了将最后一行变为非法,可将函数声明为const
一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。
在类的成员函数中,任何不会修改数据成员的函数都应该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。
一方面,对于类库的设计这来说,有责任提供尽可能多的错误检查机制减轻使用者的debug负担。但是,要求对于每一个变量、函数都判别其属性,思维量是比较大的;反之,限制过于宽松,或一个函数很复杂而只修改一个成员变量,被迫不能添加const,都失去了检查的意义
另一方面,const static等关键词提供的限制是非常片面的,远远不能起到库对于用户的指导作用。我希望能够探讨更为一般的面向库使用者的限制机制,能够在核心函数用法或者库执行流方面进行更为一般、灵活的提示和限制作用,最好能与编译器和开发环境相结合。
此外,我们也应该探讨,这类限制的数量上界应该位于何处。工程过极致,则丧失了robustness,这在软件行业的迭代潮流中是不合适的。
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,这在软件行业的迭代潮流中是不合适的。
相关文章推荐
- 基于QTcpSocket和QTcpServer的Tcp通讯以及QDataStream序列化数据
- 利用IIS应用请求转发ARR实现IIS和tomcat整合共用80端口
- 代理模式学习笔记
- CABasicAnimation - 上下滑动动画
- 解决MVC 时间序列化的方法
- Delphi中Variant/OleVariant转换为接口
- BEX错误记录
- Qt Runtime Error ! R6025 - pure virtual function call
- 逆波兰表示法
- PHP 数组操作方法
- 一些常用的IOS开发网站
- 调整框架的尺寸
- detail屏显示行数条数
- GRE issue写作范文:竞争利弊问题
- 你们猜对了:12306确实是让淘宝做的
- 1037. Magic Coupon (25)
- 全球移动应用用户参与度分析
- 1037. Magic Coupon (25)
- 大数据
- www.java2s.com