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

c++——内存分配、命名空间、强制类型转换

[复制链接]
gaosmile 发布时间:2020-8-2 23:33
一、C++动态内存分配:
在学习c语言的时候,我们一般都是使用库函数malloc()来进行内存的申请分配,然后使用库函数free()来进行释放申请到的内存;现在在c++里面采用了另外一种内存申请的方法:
  • c++中通过new关键字进行动态内存申请。
  • C++中的动态内存申请是基于类型进行的。
  • delete关键字用于内存释放。
    8 K) H8 a% h" @+ h& p" i/ `+ K
下面是申请内存的类型:
变量申请格式:3 E  r- ^: C5 I4 ~- X8 s/ A
3 J8 Z% ^1 I6 Q7 S, Q8 I

, I4 i* f, B! u& g/ FType* pointer = new Type;( q$ k. v: W  H- _, @) q# n
7 ]. m  z& U, p: L# ~
//8 {# d  @  }+ D9 l

. N0 M3 k3 O; pdelete pointer& \' k5 q2 X2 z, \' M4 f

3 r) W8 n  r  v0 ~" I9 C6 w" {
1 o! R7 E( y2 x  K9 v' j
7 C$ o$ i3 i. ?/ z) @; x
数组申请格式:
4 @" C8 |* B$ P- I) ?) w, a' }; j, e

- x' d( S6 s9 sType *pointer = new Type[N];
- T. W+ L3 w1 B5 f( w6 a
0 a8 `/ ~" q$ q1 y- C& B//
0 E8 S8 Q& ~* L0 ^" L! B$ [% Q( T8 ~" c* i
delete [] pointer;6 ~, W) v$ \" m+ ^: z9 Q5 n
  

: J0 ?5 w1 U/ i: l5 z; d
下面我们来看一个例子:
#include <stdio.h>5 o* P+ D( d+ `' N: _

9 K2 V( \; u6 ?5 T) f( bint main()% ?+ A0 F/ j" _
{
' t: M( k9 ?5 ?0 r5 H* h    int *p = new int;
; w" [8 ^" h$ b' E    *p=5;' _. B  A) i7 `! r( a5 P5 z
    *p=*p+10;6 d% z7 t; w+ Y) O
! E7 W9 f, G! W+ j) v
    printf("p= %p\n",p);
) V) k0 l# @/ r* o8 b# ~1 \5 Q    printf("*p=%d\n",*p);8 ^9 |* v, c  g4 O, k6 \; W7 n' y
" E$ v0 y; y5 H0 M
    delete p;& t" f# @. g+ O* {+ t
: y3 |2 D+ x+ j+ C7 R& i' T! V/ C
    p = new int[10];
6 s$ _  M; q1 v; I6 R5 x
% f. P7 P7 D8 L: {    for(int i=0;i<10;i++)
2 Y, ^; L0 L- J4 X+ W    {1 \/ y8 S2 i9 o9 R
       p=i+1;
& H# @: `" _* O8 x6 e/ f       printf("p[%d] = %d\n",i,p);$ ~- m& J" W1 i' S7 e
    }
1 x8 n7 E0 i) z4 Y7 ?- r2 T" B
, a3 `/ }  {9 C6 J$ s9 x' g    delete [] p;+ q$ _: I! U; o# ?$ O6 B( A

  R! C) h, n' X    return 0;
6 c( f0 m$ R, o% y* v- B
" \  _% v5 a' i* O}5 z5 E7 `* Q# W! N" A+ |7 X
+ j4 F0 r5 d1 r( O6 C
输出结果:
p= 0xb6d010
/ N9 T: o: U; K) ?6 U*p=15
7 J" j0 u0 T) E* Bp[0] = 1$ d$ u# q: f) ^0 y6 ?
p[1] = 23 t/ [. I  }0 m# E5 y' `7 s
p[2] = 31 w# x" y$ I8 m1 t
p[3] = 41 F2 N+ S- h3 R# I
p[4] = 54 n2 w- X0 w0 j1 W4 Y7 S
p[5] = 6
3 i) ]( `; |! ~7 ]: wp[6] = 7
8 j' q  D: n) Zp[7] = 8  T) B7 z5 M0 s) h$ }
p[8] = 9
# i  |0 J" ?! g: K, _p[9] = 109 `9 A7 x4 I% y; B+ r) s! p
: |" e  l6 [5 W
二、new关键字与malloc函数的区别:
1、new关键字是C++的一部分。
0 {# K, x* [: C
1 P9 }8 q6 l; H0 r$ y2、malloc是由c库函数提供的。
: j- ~7 f% j2 m: A+ l  w9 J! H/ a* q, h. [4 w- S( i7 U
3、new关键字以具体类型为单位进行内存分配。- S9 J0 j: j2 r4 }, a9 s
6 L1 X2 ~% W+ d% A+ S' V
4、malloc函数是以字节为单位进行内存分配。
. @" }: ]2 K' x: A7 G; A# E
9 Y' ~$ t; \. s1 d# p5、new关键在申请单个类型变量时可以进行初始化。
& f% [! `! c9 m) G
1 l; Q$ W9 B! Q( L* P# G" d8 i6、malloc 不可以进行内存初始化。; r+ e5 j8 X% f1 Y9 Q! X! q

" E& v" N7 _" t6 @, s
我们来看使用new关键字是如何进行初始化的:
#include <stdio.h>& C- y; v! t; a1 P
int main()/ s" U$ J: U) }& b
{
5 s( D. I2 E+ n# Y0 |9 ]( E6 H    int * pi = new int(1);
5 x2 {, O/ }4 j$ A  b    float *pf = new float(2.0f);
4 s; {) q- F- M" {5 {    char *pc = new char('c');
% a& E  _6 \# k: {7 T3 q3 V5 B# b/ K( o8 X! v
    printf("*pi=%d\n",*pi);# e0 u. F1 Z( X' Z$ s
    printf("*pf=%f\n",*pf);
( q0 _2 a5 G) v3 ]8 n% t+ u9 e/ X9 O    printf("*pc=%c\n",*pc);
( ?* `- \7 q' o; _( ~6 W$ _# V' s: F8 O6 F' r
    delete pi;
( c' N! \0 l9 K  O    delete pf;/ h" s3 b2 b2 P+ G
    delete pc;
- c5 n/ P1 z9 U+ Y6 C- n; i6 t
4 H  [% q% z1 ~   return 0;- @, u. n9 j' m6 w8 p0 k
% @0 ~) _4 a" P7 Z7 K
) C3 E$ u0 K3 k/ G
}
  |: V6 B) F4 Q
4 Y& J2 P% w) l9 @
输出结果:
*pi=1% u/ T/ j. w4 S6 y
*pf=2.0000001 m" C6 y( V. J' `2 h
*pc=c
/ M$ b# G; I( b+ a$ b5 }5 b

+ o8 j& H& [: K' k$ V
三、c++ 中的命名空间:
在c语言中只有一个全局作用域:
  • c语言中所有的全局标识符共享同一个作用域。
  • 标识符之间可能会发生冲突。-
    0 _; k' I* u7 t. w' k
c++中提出了命名空间的概念:
  • 命名空间将全局作用域分成不同的部分。
  • 不同命名空间中的标识符可以同名而且不会发生冲突。
  • 命名空间可以相互嵌套。
  • 全局作用域也叫默认命名空间。

    9 J% u& w' o2 W% O, I/ D" |) ^
1、下面我们来看一下c++中命名空间的定义:
namespace Name - Y9 p0 I9 L, M$ G- y+ e$ {( G
{
1 ?3 r/ T: A, K/ D4 K7 H     namespace Internal
4 M; j! \$ k' T+ y# o     {
! A& [4 H) Y. s7 |! b     
8 p+ c- a# O& N7 A* n     
0 v5 g2 @. a1 D3 p8 U% w     7 o+ @7 E3 a, i, {9 g
     }5 c# ~+ Z" o& [7 L1 v6 i. Z* c
}
# z: y; M& x3 e- _0 [' |  [6 t; L
2、c++命名空间的使用:
  • 使用整个命名空间:using namespace name;
  • 使用命名空间中的变量:using name::variable;
  • 使用默认命名空间中的变量:::variable;
    4 u2 q8 t! W! T5 L4 h) O1 Y
3、代码示例:
#include <stdio.h>
) |8 S5 Q3 E) W$ m, k5 H! A1 q. c3 h, O. m% ?
namespace First1 p. r* o; P/ R2 `, z3 M$ }0 E- T) u8 g
{
1 a9 p6 m* ]2 ~; j: U     int i =0;$ u) K0 d- l# m5 c, D2 A  Q

3 k* m" A5 w. j6 d+ M$ z}0 B8 F0 H2 d3 e* A" X  }! a
& b# J9 f. A/ m2 ?
namespace Second% s+ }- j+ b- }! c: ]4 u
{2 Q# t1 q- a# m* b% F5 t5 p& t1 n

4 m& c' v5 o, X; s% {   int i =1;
' E. W3 P( M. w/ N) N, t   namespace Internal# \; _: o1 g6 p8 R; @
  {4 J- J9 W  r! p* N/ i
4 k9 b# L& Y- Z! V' d# H) e
     struct Test, R' }4 L0 }" Q+ [1 T
     {
5 z  a, q8 S$ o* ~3 F7 \$ U         int x;9 S' d* ^8 k& P' o( I( B  {
         int y;
+ X+ X+ }$ o8 I& R9 W3 ~
! E8 x- M9 v5 ]! g6 A% a5 t/ z     };/ m& G" C6 ^" ^0 ~. i
% I6 x( B' U0 x
  }
/ L: l# p2 M- ?1 q. h4 J9 }5 l. g1 I6 j, V* A
}
' N+ v! k* _5 Cint main()
0 l4 K6 h6 X* N8 V, g" e( w8 a{
. W: n( w) v! {* K% P   using namespace First;
# [# Z1 ]5 J9 M- B& [2 k" o   using Second::Internal::Test;
- }1 B' t# Y3 X/ W9 K8 G* t& a- N. t7 @' M  o3 p/ V
   printf("First::i is %d\n",i);
) C9 W; v, d5 c; d' i& ]   printf("Second::i is %d\n",Second::i);
) _5 ]! b7 u" f) w& |6 r
& ]1 F9 g( F' V2 l  Test i={2,4};7 G+ f% ^/ e6 Z% e* G! o# j9 @
1 m, `! X, k: O5 Z( v
  printf("i.x is %d\n",i.x);
8 B( Z. t6 g7 M  printf("i.y is %d\n",i.y);/ K0 D$ {. n- [4 I3 P* s# t+ w

- \  }, J8 G: k  D, P& g  return 0;
& J* G, Y8 L2 D) a& i. }
( B2 J' W6 `. ]- {' E4 E0 x- r
$ Y3 ~* ?' a, A2 B7 c* E' ], A7 d6 Y
" f: S+ `" y2 X& ?7 A: a}) ~* I  I% b: l( F& g3 L
2 O" }5 D6 Q; }0 H
输出结果:
First::i is 06 v; Z8 _; A, h6 ]. L2 Q; D
Second::i is 1
$ K  E% f& U4 S' ~8 Si.x is 2
( Q- q: l) a0 r# i! c; C, li.y is 4$ i3 D0 A6 k+ Z) y9 k6 t

* D8 r! x/ q: }" L6 k* S) _4 a
四、c++中的四种强制类型转换
  h# F5 n' I- U- i$ g4 v
强制类型转换类型汇总

) ^% U5 t! E! }' }static_castconst_cast; t5 N5 V$ m$ U, ?, P( T3 V9 c
dynamic_castreinterpret_cast
用法:xxx_cast(Expression)
下面是每种强制类型的具体讲解:
1、static_cast强制类型转换:
  • 用于基本类型之间的转换
  • 不能用于基本类型指针之间的转换
  • 用于有继承关系类对象之间的转换和类指针之间的的转换
    1 N, F1 @: c+ I
代码解析:
#include <stdio.h>8 F; K0 c, z9 W8 n6 t/ s, r# _
+ d9 e& ~/ E6 f% g$ \( r- L6 M
void static_cast_demo()7 A3 D  G# r7 N# ~& d# C
{
3 f+ }2 j7 |0 V: I# u1 r4 l    int i =55;2 s5 L& J5 N/ B! Q' O
    char c ='c';
7 U3 {; n/ G5 Q. z, ?    int *pi =&i;) E( m6 @9 X5 X. F; j* a; A
    char *pc =&pc;5 x" v( f7 }1 l9 a
( P5 l4 S+ ?" S& m8 ~; M
    c=static_cast<char>(i);% Y) x  w7 S; J# [# U1 n# H$ T- N! _
    pc=static_cast<char*>(pi);
6 e1 F$ u5 [" Y" l4 ]( g/ H9 D2 o0 E+ ^# @; B( E6 U! ^
}
9 I8 b6 k$ |% s4 G. yint main()
/ n' Z5 O3 @; P% j# a{6 G  h6 p" Y1 G$ V0 W; q
    static_cast_demo();+ w7 e/ q" W$ P$ [& T
3 }4 G& k! Q, K. H" ~
    return 0;
. l" H; e) R. }
: F, x" ]/ u& Y, _6 H$ S. L' d}1 X2 a1 `# o" v5 z5 e4 F# ]' ~

6 d& u5 j' }( }; j1 F1 H/ A
输出结果:
t.cpp: In function ‘void static_cast_demo()’:
2 ~7 C) e+ \& B  X8 c/ M2 Ot.cpp:8:16: error: cannot convert ‘char**’ to ‘char*’ in initialization" {6 ~+ T! |7 `! |; }/ W4 L+ ~; w
     char *pc =&pc;
0 W/ l" Q" t/ `4 H! d( \$ {. D                ^
* ?; I; X5 `; {5 {2 Bt.cpp:11:29: error: invalid static_cast from type ‘int*’ to type ‘char*’& P  ^. X2 E+ U& K7 Q
     pc=static_cast<char*>(pi);
  ?" l' B+ L0 ^+ p) o5 Z: P                             ^# ]( A) D. b7 H9 T

& Q. }, Z- Z& c1 X5 W4 C
刚好验证了我们上面说的static_cast不能用在基本类型指针之间进行强制转换。
2、const_cast强制类型转换:
  • 用于去除变量的只读属性
  • 强制类型转换的目标类型必须是指针或者引用
    " Q+ C; F, l: i0 W; Q* v7 U  ^
代码解析:
#include <stdio.h>
5 y8 H2 Z7 w8 b% j: s1 q, C! ^7 S0 a; W+ ?% v
void const_cast_demo()3 _8 b+ q9 C; x6 m/ H7 ^8 O, y
{6 j& H8 e6 D( Q% x0 y: Y
    const int& j =2;
0 ]8 Q' q) a, G3 f; M5 z    int& k = const_cast<int&>(j);% s  P3 y$ {1 n

0 _, ~, F! R6 u    const int x = 4;
- X% `9 x9 i- m4 p2 y3 x    int& y = const_cast<int&>(x);
' F' K! t* b% E0 T$ D0 O4 {- _& j) v/ Y; X3 }' B) H
    int z = const_cast<int>(x);3 k/ l  @9 r; X) p' J6 Y: ^
1 k9 B# b) _3 ?5 P% w( b  n
    k=8;
0 ~3 O8 [+ O, Z: Y& M
' n& C  ^9 _3 ]  J5 w   printf("k=%d\n",k);
2 t* s* E  ?7 H- B   printf("j=%d\n",j);6 b. L, q8 ]( c4 O
! S) Y9 W/ v& F+ z$ x
   j =12;
+ F9 V0 l' W% K& u' G2 }: W
3 s. ^) H8 i; z# d   printf("x=%d\n",x);
* u  C4 P. N" n, u7 t7 H   printf("y=%d\n",y);: \! w/ Z- f5 x1 S, U. r% s9 y; \
   printf("&x=%p\n",&x);; _! X& ]: i( X
}% J/ w- G( X% x- y
int main()5 }' ]( h. G, C6 F. N6 T
{
! e' w, J0 P$ x7 ^0 x+ N    const_cast_demo();
6 M0 n$ y0 ]4 f0 A. ]5 E
( |6 Q- f! V5 d4 E( q    return 0;
1 d7 j# ~; ~" @: Y, h+ t( T+ Z1 g" c3 H" w8 L* k6 ^) J/ b: f
}& a; _5 p. h- X5 ^! ?9 Z
$ Q- S5 T4 d. J( g/ i  d# g2 ?' j
输出结果:
t.cpp: In function ‘void const_cast_demo()’:4 J2 ?9 C; T, {5 }9 D7 g/ x
t.cpp:11:30: error: invalid use of const_cast with type ‘int’, which is not a pointer, reference, nor a pointer-to-data-member type1 L- C' k7 y: T
     int z = const_cast<int>(x);8 E3 G' O: V" F% A
                              ^4 X$ i7 @7 }3 n2 y% w6 M7 v& f
t.cpp:18:6: error: assignment of read-only reference ‘j’4 K7 C' ?" h' v3 J) r
    j =12;
: {2 U2 x  f/ z. g0 E+ w& D

! W- o' g+ W2 i, D- Q9 v
通过上面的z转换,我们可以发现它的目标不是指针或者引用,所以报错。
3、reinterpret_cast强制类型转换:
  • 用于指针类型之间的强制转换
  • 用于整数和指针类型之间的强制转换

    6 E8 o! G3 i* B2 O: E& i
代码解析:
#include <stdio.h>) D/ l) K3 Z0 G0 H+ _' _3 G2 g  \
void reinterpret_cast_demo()
- I  N* n( Q2 }- |" {5 \, U2 y! t{) ]' {( r" L8 g: T+ `8 `9 d1 e  C
    int i =2;( ]0 Q8 p: C# r3 \) F
    char c = 'c';
  v0 J' f6 W- ?: Y# I0 X$ y    int *pi = &i;, m. J8 |- n& i
    char *pc =&c;" J$ H* `% _/ k9 V

& U( ~1 Z( ?' b9 v$ ]6 n( u    pc=reinterpret_cast<char*>(pi);0 K% j% I% i6 v' y
    pi=reinterpret_cast<int*>(pc);" G; @( m/ ?+ m6 O- ?
    pi=reinterpret_cast<int*>(i);
3 g( J) v, h& ?/ a! |    c=reinterpret_cast<char(i);
; ?+ V; k1 u. H+ w% O' w/ {
0 P# V  a: n+ u* D! R" p' v5 h- W! L( l; Y
}
# L; u1 Z; J: H5 K2 a! o* E
2 x7 U6 ?- V6 U5 z6 sint main()8 g, X8 T2 N% i. ^8 H/ d
{
7 X- H, A9 a1 i- W. l7 p2 k    reinterpret_cast_demo();7 ^2 V+ l, ~$ B
9 r% A' O& G5 `+ B. ~- O
    return 0;
: z  j; s1 K9 a9 d; b# [% W  `. Y$ E; i" D+ y' A1 i
}4 r+ I) r. T4 ?4 e" x( \. m7 C; t, Z

! J% Y9 {, k. G3 [" A( R1 V
输出结果:
t.cpp: In function ‘void reinterpret_cast_demo()’:
6 e& [1 N- o# P1 Yt.cpp:12:28: error: expected ‘>’ before ‘(’ token
( P7 f8 U4 s* L3 x9 ]  F     c=reinterpret_cast<char(i);4 e. A- _( d- B7 |) b; T
                            ^9 [" t4 g! y. h4 @- Z! O
t.cpp:12:30: error: invalid cast from type ‘int’ to type ‘char’/ g" x9 d4 G0 c
     c=reinterpret_cast<char(i);; w% \3 h6 g9 r8 V# ?0 Z9 {

: n  u9 i- v, i1 G) O
从结果我们可以看到,它用于整数之间的转换,不符合规则,所以报错。
4、dynamic_cast强制类型转换(暂时有些概念没有学到,先记住结论):
  • 用于有继承关系的类指针之间的转换
  • 用于有交叉关系的类指针之间的转换
  • 具有类型检查的功能
  • 需要虚函数的支持

    " e4 q% o' C8 H7 l' B0 W9 W! |% U
代码分析:
#include <stdio.h>
& p/ Q! W2 W7 \, Ivoid dynamic_cast_demo()
- `* m8 |* [: H! l6 E{( K  G4 j: G+ ]3 s/ T3 y
      int i =2;
3 p* M+ \* x' S5 d1 V4 k8 P      int *pi=&i;
, z; T! H1 u; F' f( |      char *pc =dynamic_cast<char*>(pi);  F2 ?1 s1 ]0 W
/ r4 [& x# p; B8 O6 g7 s
}
% ~" a7 }. Y" U  T( t( Z$ X; ]8 D4 o( b+ H* N, U
int main()  X% E9 s: G( A2 X
{7 b) A" l0 k; M* r+ ]& I
    dynamic_cast_demo();
3 Y, A4 t4 x" ]0 C3 W
3 t/ \$ a7 `8 n( e    return 0;
, W$ o9 Z9 m" [* _" F" K# n; ]- J1 g- b$ z. Y
}
- c! P8 i: |* ?) a6 f8 z6 P

2 a8 z; H, T, e8 a
输出结果:
.cpp: In function ‘void dynamic_cast_demo()’:2 ~4 _6 D' `3 z, C* F% [
t.cpp:6:39: error: cannot dynamic_cast ‘pi’ (of type ‘int*’) to type ‘char*’ (target is not pointer or reference to class)
1 ?7 \+ [/ f- I. G* F$ v2 L       char *pc =dynamic_cast<char*>(pi);
! S9 }! m( g  {* }- h3 c/ ~6 Y( ~

3 Y+ s7 U2 ^2 T2 l. F7 U8 R
不符合规则,所以报错。
5、小结:
上面四种类型转换的例子,前三种把错误的地方给屏蔽掉,就是正确的例子,第四种类型转换,暂时继承的概念没有学到,所以这个例子不是很好。
同时内存分配的使用,本次也只是简单的说了一下概念,在真正实操当中,还是有很多要注意的地方,下期文章我们再详细解析。
5 n- I! I0 z+ J% o
赞 收藏 评论1 发布时间:2020-8-2 23:33

举报

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