c++中 const 和常量的区别是啥?

2022-12-21 0 352

简而言之自变量,是在URL运行操作过程中值静止维持不变的URL,该URL的值能是两个物理量,也能是数组。

在C/C++中,一般来说采用define宏表述或是const来表述自变量,比如说:

#define PI 3.1415926const int a = 5;

接下去他们来归纳const自变量的有关用语与小常识。

为甚么采用自变量?

1. 采用自变量可减少流程的时效性。

开发人员假如都有此种历经:看他们的URL索莱米URL中某一位数而苦恼,不知道那个位数则表示甚么象征意义,即使他们写的URL,过一两年再转头看,有可能都不提过URL里某一位数代表者甚么原意。比如说排序六天包涵的步数,假如依照下式排序,尽管要说,但很可能会让人懵逼。24代表者甚么?三个60又依次代表者甚么?

int s = 24*60*60;

较为所推荐的作法是类似于此种的,此种看上去就较为明晰了:

const int oneday_hour = 24; const int onehour_minute = 60; const int oneminute_second = 60; const int oneday_second = oneday_hour * onehour_minute * oneminute_second;

2. 采用自变量可减少出错的概率。

开发人员写URL时,经常需要在多个地方采用同两个位数或是同两个数组,假如都是直接输入位数或是数组,万一某一地方写错了,造成该处与其它地方的位数或数组不一致,很可能导致严重bug。

比如说以下URL,多个地方要用到Π值3.1415926,假如把3.1415926表述为两个自变量,采用起来就方便多了,也不容易出错:

//不好的采用示例 double a = sin(3.1415926*5); double b = cos(3.1415926*10); double b = sin(3.1415926*100)*cos(3.1415926/2); //所推荐的采用示例 const double PI = 3.1415926; double a = sin(PI*5); double b = cos(PI*10); double b = sin(PI*100)*cos(PI/2);

3. 采用自变量能减少URL维护的工作量。

采用自变量的情况下,开发人员维护URL时假如要修改URL中某一数值,他只需要修改自变量的值,那么URL中多处用到该自变量的地方也就他们改了过来,而不需要开发人员去两个地方两个地方地修改。

比如说以下URL,排序b、c、d都要要到5.0那个数值,假如哪六天需求改变,需要把5.0改为20.0,在不好的示例中需要修改三行URL,在他们所推荐的示例中只需要修改一行URL——把自变量a的值改为20.0即可:

//不好的采用示例 float b = 5.0*3; float c = 5.0 + 10; float d = exp(5.0); //所推荐的采用示例 const float a = 5.0; float b = a*3; float c = a + 10; float d = exp(a);

4. 采用自变量可提升流程的健壮性

编写URL时,他们经常希望某两个变量的值不被意外改变,或是某指针指向的对象不被意外改变,又或是某指针指向的对象的值不被意外改变(这里可能有点懵逼,读者暂时不用苦恼,下文他们再详说)。然而在URL的汪洋大海中,难免会有意外发生,他们能做的是采用自变量来减小此种意外发生的概率。

比如说以下函数,指针p作为输入参数,在该函数内部他们不希望p由其原本指向的地址被改为指向别的地址,同时希望指针p指向地址的值是能改变的,那么能采用const来修饰p,此种p指向的地址就不会被意外改变啦~

void func(int *const p) { int a = 3; p = &a; //此种的操作是无效的,因为指针p被const修饰,其指向的地址不能被改变 *p = a; //此种的操作是有效的,p指向地址的值会被修改为a的值 }

const自变量与define自变量的差别

在C/C++中,有const和define两种表述自变量的方式,不过const自变量相比define自变量有更多的优点:

1. const自变量有数据类型,define宏表述自变量没有,编译器会对const自变量能进行数据类型的安全检查,但是对于define宏表述,编译器只是将其进行字符替换,此种的字符替换很容易出错。比如说以下URL,假如采用不加括号的宏表述,将不能正确排序(a+b)/5.0,而是变成排序a+(b/5.0)了。

//define宏表述的作法 #define a 2.0 #define b 9.0#define c1 a+b //不好的表述方法 #define c2 ((a)+(b)) //所推荐的表述方法 void func1(void) { float d1 = c1/5.0; //本意是想排序(a+b)/5.0,但字符替换使排序变成了a+b/5.0 float d2 = c2/5.0; //正确排序了((a)+(b))/5.0 = (a+b)/5.0 } //所推荐的const自变量的作法 const float a = 2.0; const float b = 9.0; const float c = a + b; void func2(void) { float d = c/5.0; //正确排序了(a+b)/5.0 }

2. 有一些调试工具能对const常量进行调试,但却无法调试define宏表述自变量。

因此,他们还是建议尽量采用const自变量。

建议的const自变量表述规则

1. const自变量应在.c或.cpp文件中表述,尽量不要在头文件中表述,因为假如头文件被多个.c或.cpp文件包涵,那么表述于头文件中的自变量将被多次重复表述,很可能造成严重错误。比如说以下URL:

所推荐的作法,在.c或.cpp文件中表述:

const int x = 15;

不建议的作法,在头文件中表述:

#ifndef _TEST_H_ #define _TEST_H_ const int x = 15; #endif

尽管不建议在头文件中表述自变量,但是对于全局自变量,也是他们不仅希望该自变量能在其表述的.c或.cpp文件中采用,还能在别的.c或.cpp文件中采用,那么能在头文件中对其进行extern声明,此种一来只要别的.c或.cpp文件include了该头文件,它也就能采用该自变量了,比如说以下URL:

#ifndef _TEST_H_ #define _TEST_H_ extern const int x; #endif

2. 假如两个自变量与别的自变量有联系,在表述的时候尽量把它们的联系包涵进去:

//不所推荐的作法 const int a = 5; const int b = 5*100; const int c = 5 + 5*100 64; //建议的作法,在表述时把a、b、c的联系包涵了进去 const int a = 5; const int b = a*100; const int c = a + b 64;

容易混淆的const自变量表述

1. 某一量的值静止维持不变:

const float x = 5.0; //表述x并将x的值初始化为5.0之后,在流程运行期间x的值将保持5.0维持不变

2. 指针指向的地址静止维持不变,但能通过指针来修改其指向地址的值:

float x = 1.23; //初始化指针p指向x的地址之后,p将不能改为指向其它地址 float *const p = &x; //无效操作 float a = 6.3; p = &a; //有效操作 *p = 100.0; //等效于x = 100.0

3. 指针指向的地址能改变,但不能通过指针来修改其指向地址的值,该情况与上述第2种情况相反:

float x = 1.23; //初始化指针p指向x的地址之后,将不能通过指针p来修改x的值 float const *p = &x; //有效操作 float a = 6.3; p = &a; //无效操作 *p = 100.0; //此种并不能修改x的值,x的值还是1.23

另外,以下两种表述方式是等效的,都属于此种情况:

float const *p; const float *p;

const自变量与类

在类内部表述的const自变量,仅在该类的某一对象的生命周期内是静止维持不变的,对于整个类而言却是能改变的,也即该类的不同对象能将该自变量初始化为不同的值。

声明类时,其内部的const自变量成员是不能被初始化的,比如说以下URL是有问题的,声明类A时len的值并不能被初始化为50,而是两个不确定的值。

class A { const int len = 50; //实际len的值并不能被初始化为50,而是两个不确定的值 int x[len]; }

不过类内部的const自变量成员能通过构造函数的初始化表进行初始化:

class A { const int len; A(int length); //构造函数 }; A::A(int length):len(length) //构造函数的初始化表 { } A a(100); // 对象a的len值被初始化为100A b(200); // 对象b的len值被初始化为200

假如非要表述在类的所有对象中都静止维持不变的自变量,能通过以下两种方法:

1. 采用枚举来实现,如以下URL,不过此种做的缺陷是枚举表述的len1和len2只能是整型数,不能是浮点数。

class A { enum { len1 = 20, len2 = 58}; //len1和len2的值在所有对象中都是维持不变的 int x1[len1]; int x2[len2]; };

2. 采用static关键字,加上static修饰之后,自变量len不再保存在存储对象的区域(堆、栈等),而是保存到了静态存储区,因此对所有该类的对象来说len是静止维持不变的自变量。

class A { static const int len = 30; int x[len]; }

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务