[C++] const限定符

在定义变量时,如果希望该变量是一个只读的常量,则在变量前加const限定符即可。

1.用于基本类型

对于基本类型变量,定义只读常量有两种方式:#define预处理器编译指令和const限定符,前者是C中的语法,后者是C++中特有。

#define和const的区别

#define#include一样,是一个预处理器编译指令,如:

#define SIZE 21

该指令告诉预处理器,在程序中查找SIZE,并将所有的SIZE替换成21。
因此,#define工作方式和文本处理器中的全局搜索并替换命令相似。

在C++中,可以使用const来创建符号常量:

const int SIZE = 20;
//或者
#define SIZE 20

然而,如果有些头文件需要在C和C++中都可用的话,那么必须使用#define

应在变量声明时就对const进行初始化,否则将编译失败:

const int s;//s未提供值,因此编译器将提供一个不确定值
s = 20; //s 已经被编译器赋值,因此将失败

2.用于指针

有两种方式可以将const用于指针,且这两种方式之间有微妙的变化:

  • 1.使用const让指针指向一个常量对象,防止该指针修改所指向的值。
  • 2.使用const让指针成为一个常量指针,防止指针改变指向位置。

先来看第一种方式:

int i = 24;
const int* p1 = &i;
//*p1 = 12;//NOT ALLOWED
i = 30;//OK

这里表示,指针p1指向一个const int类型的数据,对于p来说,*p的值为const int,因此,不能通过p1修改值。

这种方式并不意味着p1指向的值实际上就是一个常量,而是对于p1而言,这个值是一个常量。

在来看第二种方式:

int i = 24;
int j = 50;
int * const p2 = &i;
// p2 = &j;//NOT ALLOWED
*p2 = 29;//OK ,i = 29

这里表示,指针cosnt p2指向一个int类型的数据,因此,p2再不能改变它的指向位置,但是其指向位置的值依然可以改变。

其他性质

  • 1.常规变量的地址可以赋给指向const的指针:
double score = 23;
const double * ps = &score;
  • 2.const变量的地址可以赋给指向const的指针:
const double score = 23;
const double * ps = &score;
  • 3.const变量的地址不可以赋给常规指针:
const double score = 23;
// double * ps = &score;//NOT ALLOWED

score被const限定,说明不能修改它的值,如果将score地址赋给指针ps,则可以使用ps来修改score,这将使得const无意义。

所以,当char 指针指向字面量值时,一定是const char*而不是char*:

const char * p = "Hello world";

3.用于数组名

在数组作为参数的函数中,可以使用const保护数组,避免数组被修改,比如如下示例:

#include <iostream>
using namespace std;

int fill_arr(double arr[],int limit);
void show_arr(const double arr[],int n); 
void revalue_arr(double arr[],double r, int n); 
int main()
{
        double arr[5];
        int length = fill_arr(arr,5);
        show_arr(arr,length);
        revalue_arr(arr,2.2,length);
        show_arr(arr,length);
        return 0;
}

void revalue_arr(double arr[],double r,int n)
{
        for(int i = 0;i<n;i++)
        {
                arr[i] *= r;
        }
}

void show_arr(const double arr[],int n)
{
        for(int i=0;i < n;i++)
        {
                cout << "arr["<<i << "]:" << arr[i] << endl;
        }    
}

int fill_arr(double arr[],int limit)
{
        int i = 0;
        double temp;
        for(; i < limit;i++)
        {
                cout << "Enter value #" << (i+1) << endl;
                cin >> temp;
                if(!cin)
                {
                        cin.clear();
                        while(cin.get() != '\n')
                        {
                                continue;
                        }
                        cout << "Bad input;break";
                        break;
                }else if (temp < 0)
                {
                        break;
                }
                arr[i] = temp;
        }
        return i;
}

在这个示例中,三个函数都有一个参数是数组,因为数组作为参数时,传递的实际上是它的地址,因此,在fill_arr()revalue_arr()函数中,对形参修改,实际上修改的就是原始数组,而在show_arr()函数中,避免数组被修改,将形参用const修饰,而常规变量赋给const变量是允许的。

由于数组和指针在大多数情况下是一样的,因此,在数组和指针用于形参时,因尽可能地将他们声明为const,一是可以避免数据的无意识修改,二是使用const,函数可以处理const和非const数据,否则只能使用非const数据。

4.用于引用

将const用于引用时,说明该引用是一个常量引用,如果将引用作为函数参数时,应尽可能地使用const限定,这是因为,如果函数实参和引用形参不匹配时,只有当引用参数为const的情况下,C++会在必要时生成临时变量。一般有如下两种情况:

  • 1.实参类型正确,但不是左值;
  • 2.实参类型不正确,但可以转换为正确的类型。

如:

#include <iostream>
int add( int& i,  int& j);
int main()
{
	using namespace std;

	int i = 45;
	int j = 200;
	int sum = add(i,j);
	cout << "sum=" << sum << endl;
	long h = 12;
	long k = 400;
	//sum = add(h, k);//无法用long类型的值初始化int&类型的引用
    //sum = add(3,6);//非常量引用的初始值必须为左值
	system("pause");
	return 0;
}
int add(int& i, int& j) {
	return i + j;
}

在上例中,add()函数中使用long类型的数据将编译失败,这是因为,无法用long类型的值初始化int&类型的引用。同时无法使用add(3,6),但是如果将函数引用参数声明为const:

int add(const int& i,const int& j);

则以上两种情况皆可以编译。由于const的声明,当发现实参和引用参数不匹配,编译器会生成一个临时变量,然后让引用参数i,j指向这些临时变量,这些临时变量只会在函数运行期间存在。

将引用参数声明为const引用的理由有三:

  • 1.使用const可以避免无意的修改数据;
  • 2.使用const可以使函数能够处理const类型和非const类型数据,否则只能接受非const数据;
  • 3.使用const引用可以使函数能够正确生成并使用临时变量。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值