const的一点总结

来源:互联网 发布:腾讯视频 for mac 编辑:程序博客网 时间:2024/05/16 01:55

1. const常量

const int max = 100;  
 优点:const常量有数据类型,而宏常量没有数据类型。编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查,并且在字符替换时可能会产生意料不到的错误(边际效应)


2. const 修饰类的数据成员。
class A{  const int size;  …  }
const数据成员只在某个对象生存期内是常量,而对于整个类而言却是可变的。因为类可以创建多个对象,不同的对象其const数据成员的值可以不同。所以不能在类声明中初始化const数据成员,因为类的对象未被创建时,编译器不知道const 数据成员的值是什么。如
class A{const int size = 100; //错误int array[size]; //错误,未知的size}
const数据成员的初始化只能在类的构造函数的初始化表中进行要想建立在整个类中都恒定的常量,应该用类中的枚举常量来实现。如
class A{…enum {size1=100, size2 = 200 };int array1[size1];int array2[size2];  }
枚举常量不会占用对象的存储空间,他们在编译时被全部求值。但是枚举常量的隐含数据类型是整数,其最大值有限,且不能表示浮点数。

3. const修饰指针
int b = 500;  
const int* a = & [1]  
int const *a = & [2]  
int* const a = & [3]  
const int* const a = & [4]  
如果你能区分出上述四种情况,那么,恭喜你,你已经迈出了可喜的一步。不知道,也没关系,我们可以参考《Effective c++》Item21上的做法,如果const位于星号的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常量。  

左内容右本身,分别是内容不允许修改(error: *p=2;),本身不允许修改(error:p++);
const int Tcon1=9;int Tcon2=10;const int *p=&Tcon1;int* const q=&Tcon2;cout << *p<<endl;cout << *q<<endl;//*p=100; error:不能修改p指?向的内容//q++;error:不能修改q本身//两个的编译报错是:不能给常量赋值cout << *p<<endl;cout << *q<<endl;

4. const的初始化  
1) 非指针const常量初始化的情况:
A b;  const A a = b;  
2) 指针const常量初始化的情况:
A* d = new A();  const A* c = d;  
或者:
const A* c = new A();  
3)引用const常量初始化的情况:  
A f;  const A& e = f; // 这样作e只能访问声明为const的函数,而不能访问一般的成员函数;  
 
5. 另外const 的一些强大的功能在于它在函数声明中的应用。在一个函数声明中,const 可以修饰函数的返回值,或某个参数;对于成员函数,还可以修饰是整个函数。有如下几种情况,以下会逐渐的说明用法:
A& operator=(const A& a);  void fun0(const A* a );  void fun1( ) const; // fun1( ) 为类成员函数  const A fun2( );

1) 修饰参数的const,如 void fun0(const A* a ); void fun1(const A& a);  
调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const A* a,则不能对传递进来的指针的内容进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变,保护了原对象的属性。  
[注意]:参数const通常用于参数为指针或引用的情况,且只能修饰输入参数;若输入参数采用“值传递”方式,由于函数将自动产生临时变量用于复制该参数,该参数本就不需要保护,所以不用const修饰。
[总结]对于非内部数据类型的输入参数,因该将“值传递”的方式改为“const引用传递”,目的是为了提高效率。例如,将void Func(A a)改为void Func(const A &a)
  对于内部数据类型的输入参数,不要将“值传递”的方式改为“const引用传递”。否则既达不到提高效率的目的,又降低了函数的可理解性。例如void Func(int x)不应该改为void Func(const int &x)

2) 修饰返回值的const,如const A fun2( ); const A* fun3( );  
这样声明了返回值后,const按照"修饰原则"进行修饰,起到相应的保护作用。
const Rational operator*(const Rational&  lhs, const Rational&  rhs)  {  return Rational(lhs.numerator() * rhs.numerator(),  lhs.denominator() * rhs.denominator());  }  
返回值用const修饰可以防止允许这样的操作发生:Rational a,b;  
Radional c;  
(a*b) = c;  
一般用const修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。
原创粉丝点击