找回密码
 注册
关于网站域名变更的通知
查看: 68|回复: 0
打印 上一主题 下一主题

学C+ +经常会犯的错误

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2023-5-26 14:34 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
# u( w0 O# _( n2 _# }; T7 h
2 X) `, j3 K+ N, y

- D3 A0 A1 [9 a( F1 d& l  G/ \学习C++你是否会有以下几点误解?
0 n$ i+ S8 _  N0 K& E' b" K7 Y" V4 h0 e4 a( `  Z, @4 g
! |& l' a" w& ?6 @) V7 ?
- I( d9 k% O$ O
1. “要理解C++,你必须先学习C”
- W8 f2 X9 ^8 A& o  H- _8 B4 }0 h* I# ?: B  @2 V8 U- J; D' P( b# l1 h* B
2. “C++是一门面向对象的语言”8 Q* K$ V  }3 M# I) p- A
6 Q0 [- q4 R( x" T; G; B, Y" w* E, \. M! {5 i, Y! w0 G+ \2 ~# p1 P$ c  y: J
3. “为了软件可靠性,你需要垃圾回收”: G! L" m8 h6 u3 [3 c7 U( y0 {( J! H4 Y/ g
; u4 h5 b( g  J
4. “为了效率,你必须编写底层代码”3 x1 e. X3 i9 E' b# K- _- X
4 p+ K. U8 g5 h
: ~3 a3 f3 G+ z* M: r8 [! l5. “C++只适用于大型、复杂的程序”) Q6 D* X7 _! C# J- [( y2 x4 h' o0 X5 v
  w! Q3 Z" h( K& v& r( w; ]8 N
9 k3 ]8 _) w3 X0 Q3 J* M如果你中*了,说明这篇文章适合你看。对某些人,某些任务,在某些时间,其中一些误解曾经只是正确的。然而,在如今的C++,应用广泛使用的最先进的ISO C++ 2011编译器和工具,它们只是误解。( n9 M4 e9 U9 C# C

1 Q5 n+ d) W+ c- F3 m下面来一一解释; R, W* M( H# w" H' Z$ t( }0 q0 w5 e$ S
! r7 g" h' l0 p* j  S9 e
6 V& _/ g0 a$ K0 {误解一:“要理解C++,你必须先学习C”# c& V) b! d$ \: ?
1 n" h: x+ Q9 d1 W; ~: j! m/ C) F8 v( k8 E+ J4 M( D
学习C++基础编程比学习C要容易地多。
, |+ F1 ]) j/ o* l1 I: a5 c% ^
3 d* L/ ~/ L, pC几乎是C++的一个子集,但是它不是最先要学习的最好的子集,因为C缺少计数支持,类型安全,和易用的标准库,而C++为简单任务提供了这些。
& k6 I; C/ |. U, |: ~9 @' g" A+ D! C& Z# S) n# v4 m7 z, a. E/ B+ J, x3 R" `8 Z
误解二: “C++是一门面向对象的语言”
0 i' R" F* [" w* d/ N( {* }% N2 h0 D% i9 P' V6 N+ t" N0 w9 @- Y3 w' a
C++支持OOP和其他编程风格,但它并不局限于狭隘的“面向对象”。它综合地支持了包括面向对象和泛型编程技术。通常,一个问题的最优解决方案,包含不止一种风格(范例)。“最优”,我指的是最短、最易于理解、最有效率和最易于维护等。" ?( K+ `' D( b& ~: _% T
% s* t; m( M* q4 Q8 O! M9 G. {7 S. p: D. c. q" d' a" w$ Q8 M
5 z. Z# E2 n' l: o. G! f/ W) T“C++是一门面向对象的语言”使人们认为C++不是必要的(当与C做比较时),除非你需要一个巨大的类继承层次以及很多须函数(运行时多态)——对很多人和很多问题,这样应用并不合适。相信这个误区导致C++因为不是纯面向对象而遭到谴责;毕竟,如果你把“好”和“面向对象”等同起来,那么C++明显包含了很多不是面向对象的东西,一定会被认为是“不好”。不管是哪种情形,这个误解为不学习C++提供了一个很好的借口
! Y; w; }+ Z& G1 @5 ]& C) N2 g% p. B, y+ w; r2 l
误解三:“为了软件可靠性,你需要垃圾回收”
4 y$ k- O& C* N, V* ]6 X5 ^$ D7 t" G
6 @( W, X. j& d. o在回收不再使用的内存上,垃圾回收做的很好,但是并不完美。它并非灵丹妙药。因为内存可以被间接地引用,并且很多资源并不是普通内存。
# R) I2 u" w- b8 T" @; S% x3 U2 F, @& @% N" a& u; \/ X
' Q& f& O8 T& `" [% H误解四:“为了效率,你必须编写底层代码”; q$ s' W3 a0 t; ~2 _. L+ ~2 d# r
( K) ^2 f$ J2 {: I) |
许多人相信高效率的代码必须是底层代码。一些人甚至认为底层代码天生就是高效的(“如果代码很丑陋,那它一定很高效!一定有人花费了大量时间和精力来优化它!”)。当然,你仅仅使用底层代码是可以写出高效代码的,并且有时在直接处理机器资源时必须使用底层代码。+ ~% k4 o( H% p* A
( ^" K4 a8 `7 p9 E3 M8 j9 Q/ {* ]4 e6 g; z4 b" T) L
$ l2 J% g. v2 t; D0 Q/ S; e然而,你一定要衡量一下工作是否有价值:现代C++编译器非常高效,而现代机器架构非常复杂。如果必须使用底层代码,一定要通过接口封装起来,以便于使用。通常,通过高层接口封装底层代码,会带来更好的优化(如,避免“滥用”底层代码)。在关注效率的场合,首先尝试用高层抽象来呈现需要的解决方案,而不要不加考虑地使用比特位和指针。7 }4 U0 c1 c, c& Y! S# I
0 d/ n6 t1 C6 k' U3 e7 u
+ u7 A; G% u6 A+ @7 k/ B5 Q. C! A2 H误解五:“C++只适用于大型、复杂的程序”
. n$ p- Z. y% g! W4 I2 D4 r6 S3 g8 M( C: e* Z. g! N. ]! |. _! J8 L9 h' a  l+ T
C++是一个巨型的语言。它定义的大小和C#与Java差不多。但是这并不意味着你必须知道每一个细节,或者在每一个程序中都用到所有特性。
. S' `; Y' ?$ \" p- m9 X% W. O, I* i! x3 j
接下来再说一个C++非常经典的易犯错的案例
3 X! m) C: l( T" P4 v- m3 J7 ?' `: W* ?# M
错误代码:# h% [% z  h1 F3 ?
0 |0 y& R+ e' R( X3 a* H
  R: U* H! b* c# G$ \2 Y! N" z) v4 f0 t9 O
12        bool operator( )(const GUID& _Key1, const GUID& _Key2) const{ return mEMCmp(&_Key1, &_Key2, sizeof(GUID)) == -1; }解释. F% o( x$ h) L; b9 R
$ G4 w0 `; D( w# m5 Y* x5 u# |. {9 R: G. ?
3 x* p! b8 m5 B4 A4 b不能将 mEMCpy()、strcmp() 以及其他一些标准函数的返回值,和 1、-1 这些具体的数字做比较,因为这些函数的返回值只保证大于 0 或者小于 0(译注:而并不保证大于0就等于1,小于0就等于-1)。, ~9 {( Y: u- j; W: u
- k5 b/ S3 j6 H" Q6 J& L5 o
6 L. r* ]) {, _# C2 t上面那段错误的代码可能在很长时间内都能正常工作。不过那仅仅是因为运气好而已,没什么其他原因。某一天你写的函数很可能突然间就崩溃了 —— 比如,你换了一个编译器编译源代码,或者通过其他方式优化了 memcpy() 函数。然后你的代码就不能正常工作了。  K' l, o3 d; c% H* _# x) J4 [" [
* R, m* Y1 N6 e! e6 K
4 b  w" m) o" b" ^% V9 X- c  o8 r, x正确的代码:7 e5 E$ W% e/ H7 k; B) r& h& F* r) R! y
( O$ n7 h6 B- b# k+ Q9 p$ Z
( X8 {. K' R8 `5 w8 p% B; v* A1 C: X( C6 n3 T5 m' ]8 v( c' ?& K$ v' ?
+ G( @& p. ~$ V5 f12        bool operator( )(const GUID& _Key1, const GUID& _Key2) const{ return memcmp(&_Key1, &_Key2, sizeof(GUID)) < 0; } 4 g$ V! M" {( `4 i/ ?
1 Z- W& H& n2 ]+ H8 b& T& a& F0 a4 y建议
7 k4 R2 P. x( J( w. X7 t. U/ c# `- c9 i2 k) n: q
不要依赖函数本身的行为。如果文档上说一个函数能返回一个不等于 0 的值,那它就是这么实现的。也就是说这个函数可能返回 -10、2 或者 1024。你可能经常看到函数的返回值就是 -1、0 或者 1,但是这并不能保证它每次都会这么做。, @( v0 j* b6 {. T& d1 W8 O7 P# x, ?$ U( L/ Q/ Z7 d6 o, ^' B5 ]
1 e+ X* g: E3 h6 @8 |4 f
9 w/ m! _- L9 |2 F) ^& b4 t: s这个错误是通过 PSV-Studio 静态分析工具扫描分析得到的。错误文本如下:V698 表达式 “memcmp(…) == -1“ 是不正确的。这个函数可能的返回值不一定只有“-1”,而可能是任何负数。请考虑到使用 “memcmp(…) < 0 ”来替换。0 S4 l0 p) d8 d
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-8-23 08:07 , Processed in 0.140625 second(s), 27 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表