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

c++里面的const关键字和引用

[复制链接]
gaosmile 发布时间:2020-8-28 20:54
今天给大家分享一下这段时间学习c++的总结学习:c++里面的const关键字和引用。
一、const关键字的总结
1、const什么时候为只读变量,什么时候又是常量呢?
(1)const常量的判别规则:
  • 只用字面量初始化的const常量才会进入符号表
  • 使用其它变量初始化的const常量仍然是只读变量
  • 被volatile修饰的const常量不会进入符号表
  • 在编译期间不能直接确定初始值的const标识符,都被作为只读变量处理
    " J6 G% R* u& U9 {& I
(2)const引用的类型与初始化变量的类型
  • 相同:初始化变量成为只读变量
  • 不同:生成一个新的只读变量
    1 N" r9 X8 g/ A6 o, ]
代码版本一:
#include <stdio.h>
4 Y' `6 f# |. f/ s3 c& Y7 ^) q& C& h6 o
int main()# t0 Q3 M/ W2 }. k$ ^
{/ U9 c- @0 E0 o: H, _, y2 y
   const int x = 1;//直接得到值,进入符号表,但是还是会为 x 分配空间,只不过这个空间 x 没有用而已
% `$ g1 `6 n* r+ A7 L5 {# O   const int& rx = x;//rx代表只读变量,这个变量是编译器为x分配而没有使用的空间;引用代表变量的别名,而变量代表一段内存空间的别名,所以引用代表一段内存空间的别名
5 p0 {: N9 |5 M* J7 g  n* T2 O& y1 s1 z$ K* I
   int& nrx = const_cast<int&>(rx); //消除 rx只读属性,和rx 代表的内存空间相同,同时c++里面的几种类型转换要掌握
5 a* r" W! g9 z4 D8 c   nrx=5;
+ ^6 e! n( G/ J
; ?' Y7 c; V. z' O* V, c8 q& N   printf("x = %d\n",x);
' E3 `4 r/ B; p: f3 {( z# [& x   printf("rx = %d\n",rx);
' A3 T' V% B2 q7 J% c   printf("nrx = %d\n",nrx);
$ x2 \. n# L' B. a+ c# v) Y# ]+ [0 ~; @: x6 n
   printf("&x = %p\n",&x);4 y# u' m2 z# E% N5 Y
   printf("&rx = %p\n",&rx);5 B( P3 E* R0 b, m3 S& q" ]$ k! w/ e  N
   printf("&nrx = %p\n",&nrx);: Q' n+ _) P0 q0 [' P: u  `' Q
   ( `) ?3 s) Q' }" M  c/ c3 |

6 o8 f" x7 m4 Y0 |6 ~- W" c   return 0;
* Q2 _% b! T. x8 q+ X& e! V}! i& i6 N  {5 [* J9 M+ Y

  T5 T" S; e& v/ Q& R7 X  |
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
- n0 a: E1 R2 Lx = 1- P6 h, M" z9 Z) ?+ ~
rx = 5$ I' J) v* N; @3 F
nrx = 5
% Z  H# j" u. V* R& n&x = 0x7ffcc5fa8abc! g( X9 T& D: E) B/ J
&rx = 0x7ffcc5fa8abc
$ ^& u; V! X- U&nrx = 0x7ffcc5fa8abc) j( S7 t3 f4 H" O

' Q. v3 Q0 G2 }+ G
代码版本二:
#include <stdio.h>
( _' Z7 ~% m& `1 M5 i
1 g7 r6 L  @- J: ~& Iint main()  t- G8 c4 G) s8 F( j$ n
{% g; _- \  Q) d' C( ~& g
     volatile const int y = 2;// 只读变量,不会进入符号表
3 L% `$ v( _8 D5 A     int *p = const_cast<int*>(&y);//y被 const修饰,取到的地址也有 const 属性,这里将地址只读属性去掉
2 j) {" v1 t2 f* R4 ]; y$ o/ L3 M$ Y
      *p = 8;; [: K  W5 t: r3 V
0 {5 B9 A4 c) q% G8 ?! ?/ B* S8 f3 e  W
       printf("y = %d\n",y);
" T: I4 {' u# Y" {       printf("p = %p\n",p);/ S% ^. d: Z% a% S- Z0 m# O
0 k* G% R! W- }( ?2 h) m* q
       return 0;
9 g) L1 t9 B  w- V
+ q6 y! j' J! {% K}: t' O) f5 u" t& o* z6 \6 `, |3 S$ l( y

& [! @: l/ }- W# o. W1 Q1 ]
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out+ e! z  x3 Q  L
y = 8& S) \" A  Q# s# h# s1 Z
p = 0x7ffd785596846 D) M6 B* W; r) e" a% d. i
! V( N) R, h& B2 V8 K' }' `, E
代码版本三:
#include <stdio.h>
3 D$ C. F" F: G, ^% ?
$ a; p9 [* I& ?int main()
! V; i9 j/ c8 P8 x9 P{
1 X: M* D& a0 Y1 v, ^6 B8 Q     volatile const int y = 2;
9 L6 s2 U# t; _1 G1 _     int *p = const_cast<int*>(&y);
2 n0 j+ V2 Y' x' Q; p) A: t
; l: x/ b8 |. e& e* M7 I8 y     *p = 8;, }+ q1 g% |# Z% J- l' d

. O& r1 Q! t0 t4 s      printf("y = %d\n",y);8 F7 B. X1 Z: i' l5 U% L# i' Y
      printf("p = %p\n",p);
2 \+ i% a" I7 V) j5 x! q
4 T, f. G) V) t9 c7 i      const int z = y ;//只读变量
4 ^/ C8 |! k8 k3 @. }( {3 U+ U  f; X! b3 z3 p8 [* V
      p = const_cast<int*>(&z);5 i' e, r2 r- f( _% e7 K
: K3 D& u  Z3 X' W) W% D
      *p= 9;
, p8 ?! j; W; ]. i' B$ d! e  F6 a- R9 E3 z+ L2 J3 D
      printf("z = %d\n",z);* q: j. Z" E( p. I
      printf("p = %p\n",p);
, o7 |; g  u* F/ i, ]& k9 t4 T$ z$ a% B
       return 0;0 b' l- [: n9 V. o" P+ j" k! f# w

3 Q1 k, ^* J. F0 s}8 z' x+ [% S6 p
- c& S( b) `: Y4 U- G1 X/ n
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out. N% l- x* O- e# W
y = 8
# t, g' z- X- v/ q+ e# h0 j3 X2 mp = 0x7ffc5d651250
- @- H" L! X% A4 T- }1 X8 |z = 9
) v% [9 f) H# s7 E- n2 h* U0 Gp = 0x7ffc5d6512547 Q' r( |- g3 m! b) w* Q
" A! b. p" p$ l8 ^  r
代码版本四:
#include <stdio.h>: \: G1 C4 J& g) v- H- B( {. ?

$ B9 @+ b/ @8 g3 Kint main()
. V. n* `8 j7 k- K' N{
7 u. ^7 f) X0 Q8 X5 P$ d# S/ x     char c = 'c';
: _4 w* w; S: F* W8 Q: u* [     char& rc = c;
  b+ K9 J6 G' r9 @     const int& trc = c; // char 类型默认转换为 int;const 引用初始化类型不同,将得到新的只读变量,所以改变 rc 和 trc 没有丝毫关系,从我们的输出结果可以看出来
4 D1 ~8 H4 Y; Z9 r" x9 N! X- |  v5 U
     rc = 'a';+ _9 [# a- q7 M  g$ M
" ^, K8 Z# d" W" A- P8 F% c
     printf("c = %c\n",c);5 s( ^" \7 j2 e. _5 D
     printf("rc = %c\n",rc);
' k2 e' w6 G  X: g& W     printf("trc = %c\n",trc);
; q8 C5 Q, o/ a' h: B& O) y! e
, G2 [& U1 H' E2 t* w6 m     return 0;: X, _' y/ ^. c, k7 s9 ?
7 i% O4 \/ Y6 A" l+ Q
}1 K/ B3 V) y1 B1 N2 q
结果输出:
root@txp-virtual-machine:/home/txp# ./a.out9 P# Y$ h) J6 P, }; F6 O# n
c = a5 u# g6 O5 f' k
rc = a# W; x2 l0 e% L) d
trc = c$ J6 N1 v; N" s% }7 ?7 U

6 @) T6 Q& T- j* p" ^6 D7 Y9 y
二、引用的总结:
1、引用与指针有什么关系,以及如何理解"引用的本质就是指针常量"?
(1)指针是一个常量:
  • 值为一个内存地址,不需要初始化,可以保存不同的地址
  • 通过指针可以访问对应内存地址中的值
  • 指针可以被const修饰成为常量或者只读变量
    3 i9 u! d0 b2 T2 w1 g0 S
(2)引用只是一个变量的新名字:
  • 对引用的操作(赋值、取地址等)都会传递到代表的变量上
  • const引用使其代表的变量具有只读属性
  • 引用必须在定义时初始化,之后无法代表其它变量

    3 T& x" ]3 @& L+ V0 d! p
(3)从使用c++语言的角度来看:
  • 引用与指针没有任何的关系
  • 引用是变量的新名字,操作引用就是操作对应的变量

    2 {- ]/ L0 Y, {) U
(4)从c++编译器的角度来看:
  • 为了支持新概念"引用"必须要一个有效的解决方案
  • 在编译器内部,使用指针常量来实现"引用"
  • 因此"引用"在定义时必须初始化

    , c! ~$ {8 [/ N+ C3 u
(5)在工程项目开发中:
  • 当进行c++编程时,直接站在使用的角度来看待引用,与指针毫无关系,引用就是变量的别名
  • 当对C++代码进行调试分析时,一些特殊情况,可以考虑站在C++编译器的角度来看待引用

    7 d. a, |! i- m) ]: Z
代码实践:
版本一:
#include <stdio.h>
$ z8 M2 Y4 X( |* |+ k* J* a- m8 b* ?9 v4 }# `
int a = 2;2 H6 \! l; N3 {! N& y

7 Y) w( F% I; w6 {+ }: sstruct SV{' i6 W2 j  g" N# p
   int& x;
7 c3 O9 Q  p( h   int& y;
$ B6 q( e; \4 Z3 S5 V1 `   int& z;
! p, }  ~5 ^/ I* _1 {( T. R};
6 M( t3 ]2 k+ B0 p4 \5 qint main(): h6 a4 [0 d5 H! V: A& b/ y
{
" ?5 g0 P) G5 ^: s5 h, J  int b =4;* k2 A! o: H3 G! g" H
  int* pc = new int(3) ;
  c) J! m5 J, J: B% _5 X
, a0 j% m, X* H. z0 l# N  SV sv = {a,b,*pc};2 q! _! h* _+ {+ N2 A0 [
2 {1 c, n9 p, ~% A9 W+ I
  printf("&sv.x = %p\n",&sv.x);
# P" _- V4 n* H2 i4 c( o1 s  printf("&sv.y = %p\n",&sv.y);
8 p/ E& h  @* ^+ t  printf("&sv.z = %p\n",&sv.z);6 Q& V7 u( U; K# g
5 I5 n/ t% X3 [1 e) Q$ r
  delete pc;* F4 @5 G+ b/ a' j1 ^

) G" A1 j8 _5 s% t2 n  v( i) P  return 0;/ Q$ R! S% Q: j5 y

+ C+ b8 H6 H- T* M9 W% ~}/ P8 F  u( h! V& y
输出结果:
root@txp-virtual-machine:/home/txp# ./a.out
, b  H" k& `8 ^2 p; W4 ]  z&sv.x = 0x601050
& D% Y) K- `" g4 L&sv.y = 0x7ffee11ba794
# b/ c4 P5 r7 s# Y1 k&sv.z = 0x1cfd010/ y( |+ l. l  ~+ I
* E  I& x- R1 I% R
版本二:
#include <stdio.h>! ~; G: {, K/ G* _5 p

' A% i& H& q6 r/ _- D9 [int a = 2;. E4 a. }  [0 O+ V8 F
; ?4 {6 c  j" Z: W* q/ R
struct SV{
, D: S- t1 t6 \5 r, r   int& x;
! n: S; {5 f3 p( y' }" M0 ^   int& y;
6 a! L0 r/ q: L2 ?4 i   int& z;" Z; n4 K4 G6 e
};
, ~* h2 z+ |* U' r$ Dint main(); q: {7 @9 H! Y* K2 C' ^
{  ?; M4 J8 U* P2 L1 Z
  int b =4;
% g$ i( [* N0 K( K% X  int* pc = new int(3) ;
+ C" I: z2 B/ X7 f5 `
$ l, }/ S0 F2 B, {) C  SV sv = {a,b,*pc};
9 y) |5 o6 e: U/ O7 U; ?: [  int& array[] = {a,b,*pc};//数组中的每个元素是引用就不可以;error: declaration of ‘array’ as array of references;C++ 天生要支持 C 语言,C 语言中数组中的每个元素在内存中是顺序存放的,地址是递增的,所以在 C++ 中也要兼容这个特性,而在 C++ 中唯有引用数组破快了这个特性,所以说 C++ 中不支持引用数组;&array[1] - &array[0] !=  Expected ==> 4" u1 K8 a* F! v6 T

7 r$ B, V5 V; u' w: m/ k. j3 \% f; T
  printf("&sv.x = %p\n",&sv.x);: m! R0 j8 D" U' c+ Z  Z
  printf("&sv.y = %p\n",&sv.y);
) j6 Y! x% x  p0 R% U+ n  printf("&sv.z = %p\n",&sv.z);# M$ Q, u% d, q' q% C) @0 S& t. C
% [4 X5 u* }, Y, S8 K- B
  delete pc;
+ V. S' B5 Q( h# e# L7 v' k, O! v: D3 M% d, a# h% }
  return 0;
/ u1 X, ^- U* x% j2 r& d5 [7 F
/ m) Q4 y, @: G}' ]( ^' Q( g$ A: W* h

: ^1 O# W4 t0 ~6 s% f
输出结果:
root@txp-virtual-machine:/home/txp# g++ test.cpp
& ?: L7 o# ^8 P! N3 h% btest.cpp: In function ‘int main()’:" W2 u+ ~# Z/ ^/ O. r4 h& z
test.cpp:16:14: error: declaration of ‘array’ as array of references
) ^) ]2 M" C* D: ^$ f4 y   int& array[] = {a,b,*pc};
5 \# z, W6 b4 A! u6 v1 f* i0 I. p: B) b: l2 b, }4 `/ \
三、总结:
  • 指针是一个变量
  • 引用是一个变量的新名字
  • const引用能够生成新的只读变量
  • 在编译器内部使用指针常量实现"引用"
  • 编译时不能直接确定初始值的const标识符都是只读变量
    7 @( W9 A+ k. |* ]
好了,今天的分享就到这里,如果文章中有错误或者不理解的地方,可以交流互动,一起进步。
! l# S1 R+ N- c- @
赞 收藏 评论0 发布时间:2020-8-28 20:54

举报

0个回答

所属标签

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