C++中const的妙用

const的基本概念:

const名叫常量限定符,用来限定特定变量,以通知编译器该变量是不可修改的。习惯性的使用const,可以避免在函数中对某些不应修改的变量造成可能的改动。

下面我就const的用法来谈谈:

const的用法大致可分为以下几个方面:

(1)const修饰基本数据类型

(2)const应用到函数中

(3)const在类中的用法

(4)const修饰类对象,定义常量对象

一、const修饰基本数据类型

 1.const修饰一般常量及数组  
      const int a=10;               等价的书写方式:     int const a=10;
      const int arr[3]={1,2,3};                        int const arr[3]={1,2,3};

 对于类似这些基本数据类型,修饰符const可以用在类型说明符前,也可以用在类型说明符后,其结果是一样的。在使用这些常量的时候,只要不改变这些常量的值便好。  

 2.const修饰指针变量*及引用变量&         

      介绍本部分内容之前,先说说指针和引用的一些基本知识。

      指针(pointer)是用来指向实际内存地址的变量,一般来说,指针是整型,而且一般的大家会接受十六进制的输出格式。
      引用(reference)是其相应变量的别名,用于向函数提供直接访问参数(而不是参数的副本)的途径,与指针相比,引用是一种受限制的指针类型,或者说是指针的一个子集,而从其功能上来看,似乎可以说引用是指针功能的一种高层实现。

关于运算符&和*:

在C++里,沿袭C中的语法,有两个一元运算符用于指针操作:&和*。按照本来的定义,&应当是取址符,*是指针符,也就是说,
&用于返回变量的实际地址,*用于返回地址所指向的变量,他们应当互为逆运算。实际的情况也是如此。
在定义变量的引用的时候,&只是个定义引用的标志,不代表取地址。

举例:

 1 #include<iostream.h>
 2 void main()
 3 {
 4     int a;  //a is an integer
 5     int *aPtr;  //aPtr is a pointer to an integer
 6 
 7     a=7;
 8     aPtr = &a;
 9     cout<<"Showing that * and & are inverses of "<<"each other.\n";
10     cout<<"a="<<a<<"  *aPtr="<<*aPtr<<"\n";
11     cout<<"&*aPtr = "<<&*aPtr<<endl;
12     cout<<"*&aPtr = "<<*&aPtr <<endl;
13 }

运行结果:

     了解完指针和应用的基本概念之后,下面继续我们的话题。

const修饰指针(*):

const int* a = & [1] //非常量数据的常量指针 指针常量 int const a = &
[2] //非常量数据的常量指针 a is a pointer to the constant char
variable int
const a = & [3] //常量数据的非常量指针指针常量 常量指针 a is a
constant pointer to the (non-constant) char variable const int* const
a = & [4] //常量数据的常量指针

可以参考《Effective c++》Item21上的做法,

如果const位于星号*的左侧,则const就是用来修饰指针所指向的变量,即指针指向为常量;

如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。

因此,[1]和[2]的情况相同,都是指针所指向的内容为常量,这种情况下不允许对内容进行更改操作,如不能*a = 3 ;

[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;

[4]为指针本身和指向的内容均为常量。

const修饰引用(&):
int const &a=x;
const int &a=x;
int &const a=x;//这种方式定义是C、C++编译器未定义,虽然不会报错,但是该句效果和int &a一样。
这两种定义方式是等价的,此时的引用a不能被更新。如:a++ 这是错误的。

二、const应用到函数中

  1. 作为参数的const修饰符

  2. 作为函数返回值的const修饰符 其实,不论是参数还是返回值,道理都是一样的,参数传入时候和函数返回的时候,初始化const变量 1 修饰参数的const,如
    void fun0(const A* a );
    void fun1(const A& a);

  3. 调用函数的时候,用相应的变量初始化const常量,则在函数体中,按照const所修饰的部分进行常量化,如形参为const Aa,则不能对传递进来的指针的内容 进行改变,保护了原指针所指向的内容;如形参为const A& a,则不能对传递进来的引用对象进行改变, 保护了原对象的属性。
    [注意]:参数const通常用于参数为指针或引用的情况; 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修饰返回值为对象本身(非引用和指针)的情况多用于二目操作符重载函数并产生新对象的时候。

类中的成员函数:A fun4()const; 其意义上是不能修改所在类的的任何变量。

三、类中定义常量(const的特殊用法)

在类中实现常量的定义大致有这么几种方式实现:

1.使用枚举类型

class test
{
     enum { SIZE1 = 10, SIZE2 = 20}; // 枚举常量
     int array1[SIZE1];  
     int array2[SIZE2];
};

2.使用const 或static

 C++11仅不允许在类声明中初始化static非const类型的数据成员。
// using c++11 standard
class CTest11
{
public:
    static const int a = 3; // Ok in C++11
    static int b = 4;       // Error
    const int c = 5;        // Ok in C++11
    int d = 6;              // Ok in C++11
public:
    CTest11() :c(0) { }     // Ok in C++11
};
 
int main()
{
    CTest11 testObj;
    cout << testObj.a << testObj.b << testObj.c << testObj.d << endl;
    return 0;
}

到这里就把在类中定义常量的方法都陈列出来了。

关于C++11新特性: C++11仅不允许在类声明中初始化static非const类型的数据成员

总结如下:

  1. 对于static const 类型的成员变量不管是旧的C++标准还是C++11都是支持在定义时初始化的。

  2. 对于static非const类型的成员变量C++03和C++11的标准都是不支持在定义时初始化的。

  3. 对于const非static类型的成员变量C++03要求必须在构造函数的初始化列表中来初始化,而C++11的标准支持这种写法,同时允许在定义时进行初始化操作。

  4. 对于非static非const成员变量,C++03标准不允许在成员变量定义时初始化,但是C++11标准允许在类的定义时对这些非静态变量进行初始化。

  5. 对于static非const成员变量的初始化方式并未改变,就是在相应的cpp文件中写成int CTest11::b = 5即可,注意要在类定义之后。

四、const定义常量对象,以及常量对象的用法

 class test
{
public:
    test():x(1)
    {
        y=2;
    }
    ~test()
    {}
    void set(int yy)
    {
        y=yy;
    }
    int getx() const
    {
        return x;
    }
protected:
    const int x;
    int y;
};
void main()
{
 const test t;
 t.set(33);//error
 t.getx();
}

常量对象只能调用常量函数,别的成员函数都不能调用。

五、使用const的一些建议

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

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

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

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

  • <5>不要轻易的将函数的返回值类型定为const;

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值