你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

c++中,const的使用

[复制链接]
gaosmile 发布时间:2020-6-2 12:11
大家好晚上好,今天给大家分享的是,c++中的const的使用,在我们以前学习c语言的时候,我们已经接触了const的用法,那么在c++中,const的使用,又会有什么样的不同呢?接下来就开始我们的分享吧!每天进步一点点,日积月累你也是专家!
一、c语言中const的用法:
1、const修饰的变量是只读的,本质还是变量。. i0 H  R0 d8 ~: T7 k$ e
, ~& o6 X$ C. {6 M8 @, v# }
2、const修饰的局部变量在栈分配空间,这里举一个例子:
/ O/ G/ J% [1 t0 q1 G2 d# u& f0 e5 l6 i6 M
#include <stdio.h>- v# H9 ]6 L' q6 r: m+ M/ D

- }& {( T. j% U  q6 d$ rint main(), }+ P/ w+ ?  Z( I
{
1 b. J3 p, O2 u; v! N7 S  p    const int c =0;
2 |6 ^- |( t* }: x8 Y        int *p (int *)&c;
$ H6 U% y7 m5 ~. G1 t7 d( g- r! [8 g       
: i5 d2 H5 ~! x+ p        printf("start\n");
& S; \/ u0 }6 E! M: ?        6 Z/ S+ B& t/ T  M/ p& T5 g
        *p=6;: H' T2 w3 S+ g. z) ~
        5 b- K& p# U( D9 W
        printf=("c=%d\n",c);. p$ P9 q+ K! J2 ~& |
        4 G3 W; }6 O7 i  T& ^  }8 N
        return 0;
5 v( |% I7 j4 y}( }6 }4 t5 _  w+ J

' d1 P4 y5 v8 _; }" q7 m% ]4 z最终演示结果可以看到,c的值发生了改变:
) ^7 y  P( Z' c. ~' h0 K  v
! [& T/ X  y# t) s! jroot@txp-virtual-machine:/home/txp/c++# ./a.out
) J" u! O4 t, I2 Qstart: a$ _" s) E% @( I
c=6
$ g+ O! V0 e: h; k
9 R- s& W# g0 d2 E3 E; I
! E% j; m' b# @: f: h8 `: E' E' c: o3、const修饰的全局变量在只读存储区分配空间# @. G  U( t$ w3 m7 p$ h
  t* F2 ~) `6 G5 S; C
4、const只在编译期有用,在运行期无用。8 M# ~+ h1 e# V; a/ e' S
- i% ]; W" D0 ]& C( S3 X
另外关于c语言里面常用的const几种用法,可以我之前写的文章(小声说提示一下,当时第一次写文章,排版排的差劲,还请理解!)[color=var(--weui-LINK)]超实用的const用法
二、c++中的const用法:
既然今天主题是C++中的const用法,想都不用想,c++中的const的用法和c语言里面的const用法肯定有不一样的地方,下面我们来看具体的用法:
1、当碰见const声明时在符号表中放入常量。
# ~- X6 P! k8 g. z+ |' S; A) t  I( c9 [: G& W2 ~5 I
2、编译过程中若发现使用常量则直接以符号表中的值替换。1 I- w" F3 |" M; C5 b8 E7 \6 @% X

: ^( j$ K( z2 |  c. P; O3、编译过程中若发现下面情况则给对应的常量分配存储空间
" y6 V1 s5 N" i# A4 ]9 ^    ——对const常量使用了extern7 D9 e$ G$ u" v
    ——对const常量使用&操作符; Z5 b  i0 H  t. w# d* N
   
0 ?3 x, ?8 H' Y$ P  s  注意:c++编译器虽然可能为const常量分配空间
+ p6 F% E+ Y" Y6 V. N% U  ,但不会使用其存储空间中的值。* w' a" c: [; n2 c; G( H3 j2 M, C7 L
0 z2 @/ }8 N  D$ e3 Z  Q9 D
这里的话,还是以上面的那个例子来举例,我们现在在c++环境下来编译试试,最终结果会是什么情况:
root@txp-virtual-machine:/home/txp/c++# g++ test.cpp
% s1 v9 }% ]9 T/ l8 Oroot@txp-virtual-machine:/home/txp/c++# ./a.out
$ \7 z7 n4 E2 @) ~$ q$ ]" \start8 j5 b, t7 }( K# _. H. ]& |
c=0' m  g2 D- X( y4 b( D( k. B8 d
0 a1 ]0 M, _' J
这时候突然发现,c的值居然还是零,有点难以置信;其实不然,这就是我们上面说的,在c++中,在上面的编译过程中会产生一个符号表的概念(符号表是编译器在编译过程中所产生的一张表,这张表是编译器内部的数据结构),我们还是拿刚才的那个示例来分析:
微信图片_20200602121039.png
我们来分析一下,在c语言里面指针p初始化的时候,指向了c,然后在对指针p取值操作,也就是说,改变了这时候所p指向的那个地址(&c)处的内存里面的内容,原来是0,现在被改成了6;然而在我们的c++编译环境中,就不是按照这样来想的了,如上面的示意图,可以看到,在c++编译过程中会有一个符号表生成,那么当操作指针p的时候,由于c的值暂时被放到了符号表中了,所以的话,这个时候*p只是属于自己在那块内存中赋值操作而已,影响不到c的值了,下面我添加打印一下(*p)的值来说明:
#include <stdio.h>
2 S) r4 `0 v% W  i8 Y  T* Q2 n" _+ }1 ]8 B9 |8 u
int main()
4 U% V$ N* c( ~' T( I' G4 A7 S{$ A& C: z- b, N; y' g+ r, D, ^. z  b
    const int c =0;& M4 q! ]$ k3 S" v) k2 e5 j
  int *p =(int *)&c;7 g) p9 C$ x+ R4 ^
  
0 p  Z7 C! y7 O9 T+ ^% Y2 \# e  printf("start\n");
9 B+ n$ G  _6 k+ e( q  ; ]$ u+ U* D; \/ C' S! Q' w3 z$ m
  *p=6;
  k1 y; q& z* K( @# e  
  n$ L1 W) `# a  printf("c=%d\n",c);0 K% v/ e' G4 u9 c
  printf("*p=%d\n",*p);% }7 g% U3 y9 B% i5 O
  return 0;
  s1 r' W+ v, J( Q+ S  s$ |  r}
# E: Q! C7 b8 C8 l  L
演示结果:
root@txp-virtual-machine:/home/txp/c++# ./a.out! r% r- V5 ^6 h9 x; j! a6 Q1 g
start
6 @4 ^# l& X7 xc=08 P/ \! d- X" t
*p=6
) j) a5 Y8 a3 B; ^
6 t+ X+ Z, O2 s7 O  w# _2 n0 {
三、c++中的const与宏的区别:
1,const 常量由编译器处理;
2,编译器对 const 常量进行类型检查和作用域检查;
3,宏定义由预处理器处理,单纯的文本替换,无类型和作用域检查;
为了大家方便理解,下面我们来举个例子来说明情况,不过为了说明c++里面const修饰的变量,本质还是变量,并且只有验证一下c语言里面的const只用在编译过程中有用,在运行期没有用,这里我们先举例一个c环境的代码,然后再到c++环境中编译,做一个简单的对比,方便大家理解:
#include <stdio.h>; j. p$ R; t) B1 L! F9 r% N3 z8 m
  void f()
0 [$ x9 a* s3 t! I# Z% d8 Q3 D  {
! N5 m. ?* f1 P; h- x      #define a 3
+ L3 _) w1 W5 x8 x. }' T      const int b = 4;
8 Y1 g9 s5 q/ r% k3 F# a2 a  }8 z- Y& B& M$ ?, s
  5 w4 g& B- e4 H6 E$ ?* \: c% W
  void g()
* f) K1 K8 ?. c9 o- p0 r  {5 V% t1 p0 {" z* q: x
     printf("a = %d\n", a);% t1 x& `4 v4 a
     //printf("b = %d\n", b);
- u, g6 X% u. |  }5 u4 q# V4 t, Y- c9 u7 A5 J5 Q, z4 `
, i' y0 a. A2 s6 Z
int main()) Y8 {2 j$ c& p  W
{
7 i: W" ^" z, T3 L+ X. r) J  H     const int A = 1;/ Z. M; f, F5 B9 U9 ?
     const int B = 2;. R6 J  |( h; F+ K
     int array[A + B] = {0};
. V# m5 U. a: u" ]5 e5 @6 x1 X& A     int i = 0;
1 w* {  a/ [9 X0 [' Y1 N     for(i=0; i<(A + B); i++)
8 e! n8 s' }- w4 D) ^     {5 w' p5 c/ d7 `* D, Z
         printf("array[%d] = %d\n", i, array);4 T: J2 T) N! m! |/ |
     }
3 U! z% C4 D+ I1 I     5 E3 z/ I7 v/ R. d& V; M
     f();' n* \; e& a5 Q( ]- u' z
     g();
$ e" g8 o% \. p$ K" A- ~     " g9 E9 n7 V) ?7 z6 X" m8 D
     return 0;
& X) i' j8 S" @* w}

1 U. \0 Y3 v/ @7 k4 \
演示结果,这个是在c环境下编译的现象:
root@txp-virtual-machine:/home/txp/c++# gcc test.c, a7 f+ j; M' H! `/ L
test.c: In function ‘main’:. N- {5 X9 N, ]  R. ?& R- ^
test.c:18:6: error: variable-sized object may not be initialized1 p$ A4 t; ?. L2 _7 l7 y2 E; l
      int array[A + B] = {0};& W3 W0 R$ K, P7 b  J
      ^
4 i0 B) c" P9 {! W0 T2 s$ `test.c:18:6: warning: excess elements in array initializer [enabled by default]
* B1 Y9 ~$ g/ W; s; ?% Z0 ^" Vtest.c:18:6: warning: (near initialization for ‘array’) [enabled by default]3 x6 U, @5 `- V2 c6 e: @

6 v& _, T4 y: @! G" q* P
什么居然编译通过不了,不要吃惊,在刚才也说了结论。我们现在具体来看一下它的说了啥, “variable-sized object may not be initialized”意思是:可变大小的对象可能无法初始化,也就是说明在c语言中使用const修饰的变量A和B,本质上还是变量。这里另外再啰嗦一下,面试的时候,千万不要说const修饰的就是常量,在c语言里面真正比较好的常量例子,通过 enum(枚举)定义的标识符才是真正意义上的常量。
接下来我们在c++环境中编译看看:
root@txp-virtual-machine:/home/txp/c++# g++ test.cpp
$ z) {9 l8 M* c: b. ?7 Oroot@txp-virtual-machine:/home/txp/c++# ./a.out' _0 H: x$ f  v  C( x$ m
array[0] = 08 H, g, Z# l& g& j, D
array[1] = 08 D% j8 |3 @# V1 X
array[2] = 0
, h! b, H5 B4 R. C2 n1 Ia = 3( s5 ^7 R' o/ Z+ A& B3 d
' s2 ?$ H) V$ M
哈哈通过了,这也说明了,在c++中一般定义的变量类型,在其前面加了const修饰,它就真的变成了常量了;同时细心的你可能发现,怎么在哪个函数里面有一个宏定义啊;平时大家可能见的比较多的是,宏定义都是写在最前面,这里不要奇怪,因为编译在编译到这里的时候,只是把宏定义换成了"a=3",而且还要注意上面const和宏定义的区别:编译器对 const 常量进行类型检查和作用域检查。于是乎我把上面的那个g()函数里面的注释拿掉,再进行编译:
#include <stdio.h>* s6 N' m2 n+ Y5 _7 [+ C  W1 t+ s
  void f()5 K6 {; Y1 I$ V# s& G: [
  {. y4 C  ?( I2 q$ {
      #define a 3# \; G! N  t' i% _6 ?
      const int b = 4;2 j! @9 m8 r4 [) V  `
  }/ |% D: O8 E( W) w- \8 {1 w
  
1 \5 E; f' N, D& R+ Q  void g()3 z0 m; }4 i" y
  {
0 P, P0 v4 J  z     printf("a = %d\n", a);
6 Z4 E3 F2 Y% n. {8 A/ p. @2 {     printf("b = %d\n", b);
0 ~0 b8 g: n/ @1 K1 y2 y1 v  }
; L. Z4 B2 V8 T8 X( t
- l: F6 p- x/ C' S3 u. m int main()& v9 b' F! @  o7 V
{* ?* h4 x) }! j- g; x( |5 U: g9 j" v
     const int A = 1;
7 R/ D  B. ^  e; @- @- j     const int B = 2;3 c2 D  V0 m3 q4 Q) T
     int array[A + B] = {0};
! w" |! E/ j& M7 `     int i = 0;
( }3 }& M- |' R1 M( O     for(i=0; i<(A + B); i++)2 W% C& X% K: J6 Y5 V
     {: w$ c. }: E4 L5 K" S
         printf("array[%d] = %d\n", i, array);
# F( g( g& B* \7 K9 R7 B0 R) }     }
  L0 S5 |# R9 l7 H2 `) m% w     
% f+ n2 g" p1 F1 a+ K; k! ?" j$ `     f();
  i$ }* k* g5 k$ m% c1 C( K     g();
- c9 R9 @8 }9 G* z) K! f     
& P+ J+ o1 X) K. m: A) f% D     return 0;* @2 ?5 U$ j% |" O* t. y
}
  ^  z. Q! _4 l8 x" _4 G5 t
编译结果:
root@txp-virtual-machine:/home/txp/c++# g++ test.cpp# ~% s$ {1 i% ]
test.cpp: In function ‘void g()’:* p4 j. g1 z! O9 C% H0 M) B) s6 ]- w
test.cpp:11:25: error: ‘b’ was not declared in this scope
, L" l- x* \! b: R      printf("b = %d\n", b);' P8 E5 j0 H5 w7 r

; s7 Z3 i) I4 {% h# e  f
在g()函数里面找不到变量b,没有定义,这证明了上面所说的观点。
四、总结:
1,与 C 语言不通,C++ 中的 const 不是只读变量;  i8 f+ e: y2 z: c
& A" h: q5 _  A9 b6 k
2,C++ 中的 const 是一个真正意义上的常量;0 H. q, v& p) N% g" v
0 d3 k/ D, e5 S4 y. |2 _3 C
3,C++ 编译器可能会为 const 常量非配空间;; w0 Q. C+ T$ P* V% j
0 ?; N6 ?3 b5 X! D! }
4,C++ 完全兼容 C 语言中 const 常量的语法特性;
4 W$ w& a' t1 i9 ?
赞 收藏 评论0 发布时间:2020-6-2 12:11

举报

0个回答
关于
我们是谁
投资者关系
意法半导体可持续发展举措
创新与技术
意法半导体官网
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
官方最新发布
人形机器人运动控制、感知与智能配电
半导体创新技术与应用方向
EE架构与软件定义汽车
12V/48V 汽车智能配电(SPD)
区域控制单元(ZCU)与分区架构
关注我们
st-img 微信公众号
st-img 手机版