“旧”C功能可能比新C ++功能更好的情况?

时间:2010-07-09 10:29:36

标签: c++ c

最近我与我的老板(很长一段时间的C开发人员)进行了讨论,他们不鼓励我使用C ++流并坚持使用“好老”printf&朋友。现在我可以理解他为什么这么说并且相信我,我没有听从他的建议。

但是这仍然让我感到烦恼 - 在某些情况下,C中的某些东西仍然比同样/类似的东西的C ++实现更好吗?更好的意思是例如性能,稳定性甚至代码可读性/可维护性。如果是这样,有人可以给我一些例子吗?我主要讨论像printf / streams这样的类似差异,而不是关于继承或OOP等功能。我问这一切的原因是我认为自己是 C ++ 开发人员,因此我总是尝试编写 C ++方式

10 个答案:

答案 0 :(得分:9)

C printf() - 样式输出通常比C ++ ostream输出更快。但当然它无法处理C ++输出的所有类型。这是我所知道的唯一优势 - 通常,由于积极的内联,C ++可以比C快很多。

答案 1 :(得分:9)

C程序员有时会指出一件事,值得考虑:如果你远离宏,那么C代码行的作用就显而易见了。以此为例:

x = y;

在C中,这是一项任务,只是一项任务。 y的值是(在可能的转换之后)复制到x。

在C ++中,这可能意味着任何

  • 一个简单的任务,
  • y中用户定义的转换运算符,它删除互联网并返回与x相同类型的值
  • 有一个构造函数在熔化核电站之后从y生成x类型的对象。该值分配给x。
  • 有一个用户定义的分配运算符,它允许从一堆其他类型中进行赋值,其中y具有转换运算符,或者在某些其他方式中可从y获得。赋值运算符有一个可能会产生黑洞的错误,因为它是LHC操作软件的一部分。
  • 以上更多内容。

为了使它更有趣,每个单独的操作都可能在C ++中抛出一个异常,这意味着每一行都必须以能够回滚它改变的方式编写,当你不能说什么时,这有时很难实际上是一条线。更糟糕的是,您的程序可能会立即崩溃,因为异常发生是因为在异常展开期间调用了赋值。在C ++中,事物往往变得“垂直复杂”,这对开发人员的能力和沟通技巧提出了自己的要求。

答案 2 :(得分:4)

当你编写C ++时,编写C ++。当你写C时,写一下C.无论谁说不同,可能会对这些差异感到不舒服,或者认为C ++是一个“更好的C”。情况并非如此; C ++是它自己的语言,有自己的特性,并且主要是C兼容的,只是为了简化转换。

答案 3 :(得分:4)

就性能而言,我曾经是USACO的竞争对手。我很快发现98%的程序运行时使用了C ++ IOStreams。更改为fscanf可将开销减少十倍。在性能方面,根本没有竞争。

答案 4 :(得分:3)

我认为当你需要原始内存管理时,C风格会更好。使用C ++结构执行此操作有点麻烦,例如,您没有realloc()。

有人拒绝投票,可能从未试图探讨这个话题。


我很惊讶人们无法想象自己处于不同的位置。我并不是说每个人都应该使用C风格的结构。我说当你需要原始内存管理时,C风格会更好。有人必须编写所有这些安全类/库(包括标准库,垃圾收集器,内存池)。您从未需要它的经验并不涵盖所有情况。


另一种情况是你写一个库。使用C,您可以获得漂亮的符号表,可以轻松地与许多其他编程语言绑定。使用C ++,您将拥有name mangling,这使得在非C ++环境中使用库变得更难(但并非不可能)。

答案 5 :(得分:1)

好老C!啊,在ANSI之前的日子......< sarcasm>我当然想念几乎没有对参数进行类型检查并返回值或让编译器假设任何无类型的是int而不是错误。< / sarcasm>

但是,说真的,有一个很好的论据反对使用异常作为错误处理。我读了一个相当decent argument against exceptions的系统级工作,而且我认为问题在于你不能简单地读取一段代码并知道它不会引入C ++,而你可以阅读大多数C并说“所有错误(在这个级别)被困“或”那些无关紧要的事情。“

答案 6 :(得分:1)

我无法给你一个确凿的答案;然而,我发现这个相当过时的比较很有趣。

http://unthought.net/c++/c_vs_c++.html

答案 7 :(得分:1)

我不认为在iostreams上使用printf样式函数是合理的。 iostream只是大大加快了开发时间和调试时间,并且更不容易出错(例如,考虑缓冲区溢出,错误的%类型说明符,错误的参数数量......最大的问题是编译器无法帮助你) 。 如果您在不需要时使用endlcout不会比printf慢得多。

所以一般来说你应该使用C ++ iostreams,并且只有当分析显示关键部分因为iostream调用而花费太多时间时才会使用C风格函数优化这些部分,但请确保使用更安全的函数版本snprintf而不是sprintf。

示例:

考虑您有一个int foo变量,您在printf的许多地方,后来在开发过程中,您意识到您需要foo成为double。现在,您必须更改使用printf的每个foo样式调用中的类型说明符。如果你错过了一条线,欢迎来到未定义的行为。

最近我有一个案例,我的程序崩溃,因为我错过了一个简单的逗号,并且由于伟大的printf样式命令,我的编译器没有帮助我:printf("i will crash %s" /*,*/ "here");。这不会发生在iostreams上。

当然,你不能像使用iostreams一样扩展printf和朋友的行为来使用你自己的类。

答案 8 :(得分:1)

使用C ++功能可能会有问题:

  • 可移植性:恕我直言C仍然更具便携性
  • 混合语言编程:从另一种语言调用C函数几乎不会出现问题,使用C ++会因为名称修改而很快陷入困境等。
  • 性能问题:模板等功能可能导致代码膨胀,临时对象创建也可能产生巨大影响等等......
  • 可维护性:由于C ++比C语言更复杂,因此限制使用您期望稍后维护代码的人能够使用的语言功能。

但是,如果小心使用,某些/大多数C ++功能非常方便且有用。 请记住这句话:“使用C ++,在膝盖上拍摄自己更难,但如果你这样做,那么整条腿都会花费你的费用。”

答案 9 :(得分:0)

当我不需要通用代码时,我有时更喜欢指针和memcpy而不是迭代器和std::copy

对于iostream来说,它们既方便又可扩展,但在[f | s] printf / scanf很简单的情况下有很多情况。