c++中const的各种用法

来源:互联网 发布:网络英语哪里学比较好 编辑:程序博客网 时间:2024/05/29 08:34

C++ const 允许指定一个语义约束,编译器会强制实施这个约束,允许程序员告诉编译器某值是保持不变的。如果在编程中确实有某个值保持不变,就应该明确使用const,这样可以获得编译器的帮助。

1.const 修饰成员变量 

复制代码
 1 #include<iostream> 2 using namespace std; 3 int main(){ 4     int a1=3;   ///non-const data 5     const int a2=a1;    ///const data 6  7     int * a3 = &a1;   ///non-const data,non-const pointer 8     const int * a4 = &a1;   ///const data,non-const pointer 9     int * const a5 = &a1;   ///non-const data,const pointer10     int const * const a6 = &a1;   ///const data,const pointer11     const int * const a7 = &a1;   ///const data,const pointer12 13     return 0;14 }
复制代码

const修饰指针变量时:

  (1)只有一个const,如果const位于*左侧,表示指针所指数据是常量,不能通过解引用修改该数据;指针本身是变量,可以指向其他的内存单元。

  (2)只有一个const,如果const位于*右侧,表示指针本身是常量,不能指向其他内存地址;指针所指的数据可以通过解引用修改。

  (3)两个const,*左右各一个,表示指针和指针所指数据都不能修改。

2.const修饰函数参数

  传递过来的参数在函数内不可以改变,与上面修饰变量时的性质一样。

void testModifyConst(const int _x) {     _x=5;   ///编译出错}


3.const修饰成员函数

(1)const修饰的成员函数不能修改任何的成员变量(mutable修饰的变量除外)

(2)const成员函数不能调用非onst成员函数,因为非const成员函数可以会修改成员变量

复制代码
 1 #include <iostream> 2 using namespace std; 3 class Point{ 4     public : 5     Point(int _x):x(_x){} 6  7     void testConstFunction(int _x) const{ 8  9         ///错误,在const成员函数中,不能修改任何类成员变量10         x=_x;11 12         ///错误,const成员函数不能调用非onst成员函数,因为非const成员函数可以会修改成员变量13         modify_x(_x);14     }15 16     void modify_x(int _x){17         x=_x;18     }19 20     int x;21 };
复制代码

 4.const修饰函数返回值

(1)指针传递

如果返回const data,non-const pointer,返回值也必须赋给const data,non-const pointer。因为指针指向的数据是常量不能修改。

复制代码
 1 const int * mallocA(){  ///const data,non-const pointer 2     int *a=new int(2); 3     return a; 4 } 5  6 int main() 7 { 8     const int *a = mallocA(); 9     ///int *b = mallocA();  ///编译错误10     return 0;11 }
复制代码

(2)值传递

 如果函数返回值采用“值传递方式”,由于函数会把返回值复制到外部临时的存储单元中,加const 修饰没有任何价值。所以,对于值传递来说,加const没有太多意义。

所以:

  不要把函数int GetInt(void) 写成const int GetInt(void)。
  不要把函数A GetA(void) 写成const A GetA(void),其中A 为用户自定义的数据类型。

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

5.修饰类的成员函数提供重载

class A
{
           ......
  void f(int i)       {......} //
一个函数
  void f(int i) const {......} //
上一个函数的重载
           ......
}

      尽管函数名和参数列表都相同,void foo( ) const成员函数是可以与void foo( )并存的,可以形成重载! 我们假设调用语句为obj.foo(),如果obj为non-const对象,则调用foo()。如果obj为const对象,则调用foo()const。另外要注意,假如没有提供foo()const,则const obj调用foo()将会报错。但假如是没有提供foo(),则non-const obj调用foo()const是完全没有问题的。也就是说,non-const对象可以调用const函数,但const对象不能调用non-const函数.

      const关键字所起作用的本质,就是把隐藏着的默认的this指针参数,改成const类型。也就是说:假如void foo( )函数被编译器改写为 void foo(T* pThis),则void foo( ) const将会被改写为void foo(const T* pThis) 。i.e. 在函数末尾添加一个const,就相当于在隐藏的this参数类型前加一个const.这样做有两个效果,第一:编译器将不允许foo()const修改pThis指向的对象的成员。第二、const对象只能调用const成员函数,否则就会报错说把const T* 转化为T* 会丢失qualifier

6.可以节省空间,避免不必要的内存分配

const定义常量从汇编的角度来看,只是给出了对应的内存地址,而不是象#define一样给出的是立即数,所以,const定义的常量在程序运行过程中只有一份拷贝,而#define定义的常量在内存中有若干个拷贝.

#define PI 3.14159         //常量宏
const doulbe  Pi=3.14159;  //
此时并未将Pi放入ROM
              ......
double i=Pi;   //
此时为Pi分配内存,以后不再分配!
double I=PI;  //
编译期间进行宏替换,分配内存
double j=Pi;  //
没有内存分配
double J=PI;  //
再进行宏替换,又一次分配内存!


7.提高了效率

编译器通常不为普通const常量分配存储空间,而是将它们保存在符号表中,这使得它成为一个编译期间的常量,没有了存储与读内存的操作,使得它的效率也很高

8.将Const类型转化为非Const类型的方法

·             要大胆的使用const,这将给你带来无尽的益处,但前提是你必须搞清楚原委;

·             要避免最一般的赋值操作错误,如将const变量赋值,具体可见思考题;

·             在参数中使用const应该使用引用或指针,而不是一般的对象实例,原因同上;

·             const在成员函数中的三种用法(参数、返回值、函数)要很好的使用;

·             不要轻易的将函数的返回值类型定为const;

·             除了重载操作符外一般不要将返回值类型定为对某个对象的const引用;

·             任何不会修改数据成员的函数都应该声明为const 类型。

9.额外补充

类内部的常量限制:使用这种类内部的初始化语法的时候,常量必须是被一个常量表达式

初始化的整型或枚举类型,而且必须是static和const形式。

·             如何初始化类内部的常量:一种方法就是static 和 const 并用,在外部初始化,例如:

class A { public: A() {} private: static const int i; file://注意必须是静态的! };

const int A::i=3;另一个很常见的方法就是初始化列表: class A { public: A(int

i=0):test(i) {} private: const int i; }; 还有一种方式就是在外部初始化,

·             如果在非const成员函数中,this指针只是一个类类型的;如果在const成员函数中,

this指针是一个const类类型的;如果在volatile成员函数中,this指针就是一个

volatile类类型的。

·           new返回的指针必须是const类型的。


详细用法总结:http://blog.csdn.net/Eric_Jo/article/details/4138548



0 0