const变量的用法总结

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
修饰指针的情况,见下式:

对指针来说,可以指定指针本身为const,也可以指定指针所指的数据为const,或二者同时指定为const,还有,两者都不指定为const

char *p              = "hello";          // const指针,
                                         //
const数据

const char *p        = "hello";          // const指针,
                                         // const
数据

char * const p       = "hello";          // const指针,
                                         //
const数据

const char * const p = "hello";          // const指针,
                                         // const
数据

语法并非看起来那么变化多端。一般来说,你可以在头脑里画一条垂直线穿过指针声明中的星号(*)位置,如果const出现在线的左边,指针指向的数据为常量;如果const出现在线的右边,指针本身为常量;如果const在线的两边都出现,二者都是常量。 


4.     const
的初始化

先看一下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的函数,而不能访问一           


般的成员函数;

    [思考1]: 以下的这种赋值方法正确吗?
    const A* c=new A();
    A* e = c;
    [
思考2]: 以下的这种赋值方法正确吗?
    A* const c = new A();
    A* b = c;


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修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。
[
总结]


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


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


const char * GetString(void);


如下语句将出现编译错误:


char *str=GetString();


正确的用法是:


const 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修饰,那么该返回值的内容不允许修改,上例中a=b=c依然正确。(a=b)=c就不正确了。
[
思考3]: 这样定义赋值操作符重载函数可以吗?
const A& operator=(const A& a);


6.    
类成员函数中const的使用
一般放在函数体后,形如:void fun() const;
任何不会修改数据成员的函数都因该声明为const类型。如果在编写const成员函数时,不慎修改了数据成员,或者调用了其他非const成员函数,编译器将报错,这大大提高了程序的健壮性。如:


class Stack


{


 public:


      void Push(int elem);


      int Pop(void);


      int GetCount(void) const;   //const
成员函数


 private:


      int m_num;


      int m_data[100];


};


int Stack::GetCount(void) const


{


  ++m_num;              //
编译错误,企图修改数据成员m_num


  Pop();                    //
编译错误,企图调用非const函数


  Return m_num;


}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值