服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C/C++ - C/C++编程中const的使用详解

C/C++编程中const的使用详解

2022-11-02 11:48zou_albert C/C++

这篇文章主要为大家详细介绍了C/C++编程中const的使用,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助

1 概述:const和define的区别

先看一个典型的程序:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
#include<iostream>
using namespace std;
int main()
{
    int num = 1;
    #define t1 num + num
    #define t2 t1 % t1
    cout << "t2 is " << t2 << endl; // t2 is 2
    const int s1 = num + num;
    const int s2 = s1 % s1;
    cout << "s2 is " << s2 << endl; // s2 is 0
    return 0;
}

运行结果如注释所示,分别得到“t2 is 2”、“s2 is 0”???
分析原因:const定义的常量s1、s2,则s1的值是num+num,s2的值是s1%s1,所以最后结果为“s2 is 0”;而define定义的变量作替换后,C++把cout<<"t2 is "<<t2<<endl;语句译成了:cout<<"t2 is "<<num+num%num+num<<endl;所以结果为“t2 is 2”(1+0+1=2)

注意:define定义的内容,建议增加使用括号()

?
1
2
#define t1 (num + num)
#define t2 (t1 % t1)

具体分析define与const的区别,如下定义:

?
1
2
const float PI = 3.14;
#define PI (3.14)
  • 类型的安全性检查:const常量有数据类型,而define定义宏常量没有数据类型。则编译器可以对前者进行类型安全检查,而对后者只进行字符替换,没有类型安全检查(字符替换时可能会产生意料不到的错误,如上面的程序所示);
  • 调试:部分调度工具可以对const常量进行调度,但不能对宏常量进行调度;
  • 编译器的处理方式不同:define宏是在预处理阶段展开,const常量则是编译运行阶段使用;
  • 存储方式不同:define宏仅仅是展开,有几个地方使用则展开几次,不分配内存;const常量会在内存中分配地址(可以是堆中也可以是栈中);
  • 效率:define定义的常量在内存中有若干个拷贝;const定义的常量在程序运行过程中只有一份拷贝,甚至不为普通const常量分配存储空间,而是将它们保存在符号表中,相当于没有了读内存的操作,使得效率也很高。

2. 修饰局部变量

const约束对象的访问性质:使得对象只能读,不能写:不允许修改对象的值.

const 是constant 的缩写,“恒定不变”的意思。被const 修饰的东西都受到强制保护,可以预防意外的变动,能提高程序的健壮性。所以很多C++程序设计书籍建议:“Use const whenever you need”。

?
1
2
const int n=5;
int const n=5;

这两种写法是一样的,都是表示变量n的值不能被改变了,需要注意的是,用const修饰变量时,一定要给变脸初始化,否则之后就不能再进行赋值了。

?
1
2
3
// C    
const int num = 100;
(int *)&num = 4;   //可以间接修改

C的const表示修饰只读变量,但是我们可以恶意强制操作const对象。

接下来看看const用于修饰常量静态字符串,例如:

?
1
const char* str="fdsafdsa";

如果没有const的修饰,我们可能会在后面有意无意的写str[4]=’x’这样的语句,这样会导致对只读内存区域的赋值,然后程序会立刻异常终止。有了const,这个错误就能在程序被编译的时候就立即检查出来,这就是const的好处。让逻辑错误在编译期被发现。

如下修改都是不允许的。

?
1
2
3
4
// c++
const int i = 0;   //是一个右值,有内存实体
i = 11;          //错误:向只读变量‘i'赋值
const int a{1.1}; //错误:从“double”转换到“int”需要收缩转换,请初始化成相同类型的常量

3. 常量指针与指针常量

常量指针是指针指向的内容是常量,可以有一下两种定义方式。

?
1
2
const int * n;
int const * n;

需要注意的是一下两点:

1、常量指针说的是不能通过这个指针改变变量的值,但是还是可以通过其他的引用来改变变量的值的。

?
1
2
3
int a=5;
const int* n=&a;
a=6;

指针常量是指指针本身是个常量,不能在指向其他的地址,写法如下:

?
1
int *const n;

需要注意的是,指针常量指向的地址不能改变,但是地址中保存的数值是可以改变的,可以通过其他指向改地址的指针来修改。

?
1
2
3
4
int a=5;
int *p=&a;
int* const n=&a;
*p=8;

注意:区分常量指针和指针常量的关键就在于星号的位置,我们以星号为分界线,如果const在星号的左边,则为常量指针,如果const在星号的右边则为指针常量。如果我们将星号读作‘指针’,将const读作‘常量’的话,内容正好符合。int const * n;是常量指针,int *const n;是指针常量。

指向常量的常指针

是以上两种的结合,指针指向的位置不能改变并且也不能通过这个指针改变变量的值,但是依然可以通过其他的普通指针改变变量的值。

?
1
const int* const p;

4. 修饰函数的参数

根据常量指针与指针常量,const修饰函数的参数也是分为三种情况。

1、防止修改指针指向的内容

?
1
void StringCopy(char *strDestination, const char *strSource);

其中 strSource 是输入参数,strDestination 是输出参数。给 strSource 加上 const 修饰后,如果函数体内的语句试图改动 strSource 的内容,编译器将指出错误。

2、防止修改指针指向的地址

?
1
void swap ( int * const p1 , int * const p2 )

指针p1和指针p2指向的地址都不能修改。

3、以上两种的结合。

5. 修饰函数的返回值

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

例如函数:

?
1
const char * GetString(void);

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

?
1
char *str = GetString();

正确的用法是

?
1
const char *str = GetString();

6. 修饰全局变量

全局变量的作用域是整个文件,我们应该尽量避免使用全局变量,因为一旦有一个函数改变了全局变量的值,它也会影响到其他引用这个变量的函数,导致除了bug后很难发现,如果一定要用全局变量,我们应该尽量的使用const修饰符进行修饰,这样防止不必要的人为修改,使用的方法与局部变量是相同的。

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!

原文链接:https://blog.csdn.net/zou_albert/article/details/123846874

延伸 · 阅读

精彩推荐
  • C/C++C和C++混合编程问题

    C和C++混合编程问题

    这篇文章主要介绍了C和C++混合编程问题,需要的朋友可以参考下 ...

    C语言教程网9472021-03-15
  • C/C++C++小知识:大于0并不意味着等于1

    C++小知识:大于0并不意味着等于1

    今天小编就为大家分享一篇关于C++小知识:大于0并不意味着等于1,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小...

    修语讲编程4272021-07-18
  • C/C++C/C++标准库之转换UTC时间到local本地时间详解

    C/C++标准库之转换UTC时间到local本地时间详解

    最近遇到一个问题:数据库中存放的时间为UTC时间,但是现在要求都出来显示的时间为本地时间,所以就用C++实现了,下面这篇文章主要给大家介绍了关于...

    infoworld5572021-06-10
  • C/C++C++中new和delete的介绍

    C++中new和delete的介绍

    今天小编就为大家分享一篇关于C++中new和delete的介绍,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...

    蜗牛2018312021-07-14
  • C/C++基于Windows API分解路径问题的详解

    基于Windows API分解路径问题的详解

    本篇文章是对Windows API分解路径进行了详细的分析介绍,需要的朋友参考下...

    C语言教程网4262020-12-02
  • C/C++c++中new的三种用法详细解析

    c++中new的三种用法详细解析

    以下的是对c++中new的三种使用方法进行了详细的分析介绍,需要的朋友可以过来参考下,希望对大家有所帮助...

    C++教程网4972020-12-30
  • C/C++C语言实现运筹学中的马氏决策算法实例

    C语言实现运筹学中的马氏决策算法实例

    这篇文章主要介绍了C语言实现运筹学中的马氏决策算法,简单介绍了马氏决策的概念,并结合实例形式分析了C语言实现马氏决策算法的具体实现技巧,需要的...

    reghi8232021-06-02
  • C/C++基于Matlab实现BP神经网络交通标志识别

    基于Matlab实现BP神经网络交通标志识别

    道路交通标志用以禁止、警告、指示和限制道路使用者有秩序地使用道路, 保障出行安全.若能自动识别道路交通标志, 则将极大减少道路交通事故的发生。...

    紫极神光6382022-08-08