是否有任何理由使用C ++代替C,Perl,Python等?[关闭]


164

作为Linux(服务器端)开发人员,我不知道在哪里以及为什么应该使用C ++。

当我追求性能时,第一个和最后一个选择是C。

当“性能”不是主要问题时,Perl和Python等编程语言将是不错的选择。

我在这方面了解的几乎所有开源应用程序都是用C,Perl,Python,Bash脚本,AWK甚至PHP编写的,但是没有人使用C ++。

我不是在讨论GUI或Web应用程序之类的其他领域,而是在谈论Linux,CLI和守护程序。

使用C ++是否有令人满意的理由?


5
由于STL,我只考虑使用C ++。
dan_waterworth 2010年

46
因此,只能使用C ++才能使用C,perl和python一起完成某些工作。您在问为什么要使用C ++?
Manoj R 2010年

36
«当我要去表演时,第一个和最后一个选择是C。»是的,:D这是一个未经验证的,错误的断言。
deadalnix

16
@deadalnix:我不会这么说。C ++具有复杂的规则,可能会适得其反,因为不允许执行某些操作。走进隐形性能杀手非常容易。这很明显,因此是正确的:D仍然,实际上C ++代码有时会更快,因为您将使用更有效的算法和数据结构,而且实际上没有人优化C代码。因此,如果正确完成操作,C ++将是更安全,更有效的C语言,并且在没有兼容性问题或没有100%可用性软件的要求时,应选择C ++而不是C。
编码器

4
张贴的答案中未考虑的最佳原因直接与OP的问题有关。依赖!!!!,并不是说您的普通系统没有c ++库,但是嵌入式系统可能没有它们。在每个系统中获取程序的唯一方法是用常规C编写程序。其他所有内容只是在讨论为什么应该或不应该使用C ++。这些都没有解决为什么不更频繁地使用C ++的问题,而不论其优点如何,原因都是依赖关系。
JM Becker

Answers:


308

当我要表演时,第一个和最后一个选择是C。

这就是您应该备份的地方。现在,我不能,在所有的,对服务器开发说话。也许确实没有令人信服的理由偏爱C ++而不是其他选择。

但是总的来说,使用C ++而不是其他语言的原因确实是性能。原因是C ++提供了一种抽象方法,与我所知道的所有其他语言不同,它在运行时没有性能开销。

这允许编写非常高效的代码,但仍具有很高的抽象级别。

考虑通常的抽象:虚函数,函数指针和PIMPL习惯用法。所有这些都依赖于在运行时由指针算法解决的间接。换句话说,这会产生性能成本(但是可能会很小)。

另一方面,C ++提供了一种间接机制,不会产生(性能)成本:模板。(这种优势是通过(有时极大地)增加了编译时间来弥补的。)

考虑一个通用排序函数的例子。

在C语言中,该函数qsort采用一个函数指针,该指针实现了元素相对于彼此排序的逻辑。Java Arrays.sort函数有多种变体。其中之一对任意对象进行排序,并要求Comparator向其传递一个对象,该对象的工作方式与C中的函数指针非常相似qsort。但是“本地” Java类型还有更多重载。它们每个都有自己的sort方法副本–可怕的代码重复。

Java在这里说明了一般的二分法:您有代码重复,或者招致了运行时开销。

在C ++中,该sort函数的工作原理与qsort在C中非常相似,但有一个小但根本的区别:传递给函数的比较器是模板参数。这意味着它的调用可以被内联。比较两个对象不需要间接调用。在紧密的循环中(如此处的情况),这实际上可以产生很大的不同。

不足为奇的是,即使底层算法相同,C ++ sort函数sort也会胜过C语言。当实际的比较逻辑比较便宜时,这一点尤其明显。

现在,我并不是说C ++比C(或其他语言)更高效,也不是说它提供了更高的抽象度。它提供的是一个很高的抽象,同时又非常便宜,因此您通常不需要在高效和可重用的代码之间进行选择。


16
我现在对C ++的了解足够多,可以知道您是错还是错。而且还想加你只收到1张downvote,所以放松一下。这是互联网,投票发生了。如果在技术上合理的话,很好的答案!
克里斯,2010年

46
在运行时没有性能开销 -并非总是如此。如果查看STL向量实现,您会发现它们没有利用realloc()的优势(由于指针,长话而不能使用它们),而我所知道的所有高级语言都可以并且确实使用realloc() )在矢量展示广告中。这只是一个例子,它并不那么明显,而且都是黑白的。
mojuba 2010年

19
@ Jaroslaw,@ Steve:但是对于手动优化的代码(适用于每种数据类型),也是如此(=代码膨胀,指令高速缓存未命中)(请参阅Java的各种Arrays.sort实现)。只有您失去了高度抽象的优势。这不是模板的特定缺点,通常是代码重复的缺点。此外,这往往无关紧要,因为在紧密循环中,通常总是加载相同的代码。
康拉德·鲁道夫

18
@Jaroslaw:关于指令缓存的有趣之处在于它是一个缓存。也就是说,它不会尝试存储所有内容,而只会存储最近使用的代码。模板可能会为不同的类型生成许多相似的代码(a vector.push_backvector<int>,另一个for vector<float>,但是在使用a时vector<int>,几乎没有理由将vector<float>代码存储在指令缓存中。因此,我看不出这到底有多重要。单个模板实例化是经过高度优化的,并且通常比通用的“
包罗万象”

29
@ Steve314:您所说的“膨胀”是针对C和Java手动完成的操作。在C ++中,它可以自动化,并且编译器可以像供应商一样聪明,以使它们避免膨胀。如果我必须决定是慢速运行(如C语言)还是使用重复代码(如Java语言),那么让编译器执行复制(也许对此很聪明)似乎很好,不是吗?
2010年

166

我看到太多讨厌C ++的C程序员。我花了相当长的时间(数年)才慢慢了解它的优点和缺点。我认为最好的表达方式是:

更少的代码,没有运行时开销,更安全。

我们写的代码越少越好。在所有追求卓越的工程师中,这一点很快就变得显而易见。您只在一个地方修复了一个错误,却不是很多-您只表达一次算法,然后在许多地方重复使用,依此类推。希腊人甚至有一种说法可以追溯到古代的斯巴达人:你对此很明智”。事实的事实是,正确使用 C ++,您可以用比C少得多的代码来表达自己,而不会花费运行时间,同时比C更安全(即在编译时捕获更多错误)。

这是我的渲染器的一个简化示例:在三角形的扫描线上插入像素值时。我必须从X坐标x1开始并到达X坐标x2(从三角形的左侧到右侧)。在每个步骤中,在我经过的每个像素中,我都必须内插值。

当我插入到达像素的环境光时:

  typedef struct tagPixelDataAmbient {
      int x;
      float ambientLight;
  } PixelDataAmbient;

  ...
  // inner loop
  currentPixel.ambientLight += dv;

当我插入颜色时(称为“ Gouraud”底纹,其中“红色”,“绿色”和“蓝色”字段通过每个像素的步长值进行插入):

  typedef struct tagPixelDataGouraud {
      int x;
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  } PixelDataGouraud;

  ...
  // inner loop
  currentPixel.red += dred;
  currentPixel.green += dgreen;
  currentPixel.blue += dblue;

当我在“ Phong”阴影中渲染时,我不再插值强度(ambientLight)或颜色(红色/绿色/蓝色)-我插值法线向量(nx,ny,nz),并且在每一步中,我都必须重新-根据插值法线向量计算照明方程:

  typedef struct tagPixelDataPhong {
      int x;
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  } PixelDataPhong;

  ...
  // inner loop
  currentPixel.nX += dx;
  currentPixel.nY += dy;
  currentPixel.nZ += dz;

现在,C程序员的第一个本能是““,编写三个插值的函数,然后根据设置模式调用它们”。首先,这意味着我遇到类型问题-我该如何处理?我的像素PixelDataAmbient吗?PixelDataGouraud?PixelDataPhong?哦,等等,高效的C程序员说,使用联合!

  typedef union tagSuperPixel {
      PixelDataAmbient a;
      PixelDataGouraud g;
      PixelDataPhong   p;
  } SuperPixel;

..然后,您有一个功能...

  RasterizeTriangleScanline(
      enum mode, // { ambient, gouraud, phong }
      SuperPixel left,
      SuperPixel right)
  {
      int i,j;
      if (mode == ambient) {
          // handle pixels as ambient...
          int steps = right.a.x - left.a.x;
          float dv = (right.a.ambientLight - left.a.ambientLight)/steps;
          float currentIntensity = left.a.ambientLight;
          for (i=left.a.x; i<right.a.x; i++) {
              WorkOnPixelAmbient(i, dv);
              currentIntensity+=dv;
          }
      } else if (mode == gouraud) {
          // handle pixels as gouraud...
          int steps = right.g.x - left.g.x;
          float dred = (right.g.red - left.g.red)/steps;
          float dgreen = (right.g.green - left.a.green)/steps;
          float dblue = (right.g.blue - left.g.blue)/steps;
          float currentRed = left.g.red;
          float currentGreen = left.g.green;
          float currentBlue = left.g.blue;
          for (j=left.g.x; i<right.g.x; j++) {
              WorkOnPixelGouraud(j, currentRed, currentBlue, currentGreen);
              currentRed+=dred;
              currentGreen+=dgreen;
              currentBlue+=dblue;
          }
...

您是否感到混乱进入?

首先,要使我的代码崩溃,只需输入一个错字,因为编译器永远不会在函数的“ Gouraud”部分中阻止我访问实际的“ .a”。(环境)值。没有被C类型系统捕获(即在编译期间)的错误,意味着该错误会在运行时显现出来,并且需要进行调试。您是否注意到我正在left.a.green计算“ dgreen”?编译器肯定没有告诉您。

然后,到处都有重复- for循环存在的次数与渲染模式一样多,我们一直在做“右减去左除以步长”。丑陋且容易出错。当我应该使用“ j”时,您是否注意到我在Gouraud循环中使用“ i”进行了比较?编译器再次保持沉默。

模式的if / else /阶梯怎么样?如果我在三周内添加了新的渲染模式怎么办?我会记得在所有代码中的所有“ if mode ==“”中处理新模式吗?

现在,将上述丑陋与这组C ++结构和一个模板函数进行比较:

  struct CommonPixelData {
      int x;
  };
  struct AmbientPixelData : CommonPixelData {
      float ambientLight;
  };
  struct GouraudPixelData : CommonPixelData {
      float red;
      float green;
      float blue;  // The RGB color interpolated per pixel
  };
  struct PhongPixelData : CommonPixelData {
      float nX;
      float nY;
      float nZ; // The normal vector interpolated per pixel
  };

  template <class PixelData>
  RasterizeTriangleScanline(
      PixelData left,
      PixelData right)
  {
      PixelData interpolated = left;
      PixelData step = right;
      step -= left;
      step /= int(right.x - left.x); // divide by pixel span
      for(int i=left.x; i<right.x; i++) {
          WorkOnPixel<PixelData>(interpolated);
          interpolated += step;
      }
  }

现在来看这个。我们不再制作联合类型汤:每个模式都有特定的类型。他们通过继承基类(CommonPixelData)来重用其常用的东西(“ x”字段)。模板使编译器创建(即代码生成)我们将用C语言编写的三个不同函数,但同时要严格限制类型!

我们在模板中的循环无法执行操作并无法访问无效字段-如果这样做,编译器将吠叫。

模板执行共同的工作(循环,每次都以“步长”递增),并且可以以不会导致运行时错误的方式进行。每种类型的插值(AmbientPixelDataGouraudPixelDataPhongPixelData)与完成operator+=(),我们将在结构增加-这基本上决定如何每种类型的插值。

您是否看到我们对WorkOnPixel <T>所做的工作?我们要为每种类型做不同的工作吗?我们简单地称呼模板专业化:

void WorkOnPixel<AmbientPixelData>(AmbientPixelData& p)
{
    // use the p.ambientLight field
}


void WorkOnPixel<GouraudPixelData>(GouraudPixelData& p)
{
    // use the p.red/green/blue fields
}

也就是说,要调用的函数是根据类型决定的。在编译时!

重述一下:

  1. 我们最小化代码(通过模板),重复使用通用部分,
  2. 我们不会使用丑陋的骇客,我们会保留严格的类型系统,以便编译器可以随时检查我们。
  3. 最重要的是:我们所做的一切都不会对运行时产生任何影响。该代码的运行速度与等效的C代码一样快-实际上,如果C代码使用函数指针来调用各种WorkOnPixel版本,则C ++代码将比C更快,因为编译器将内嵌特定于类型的WorkOnPixel模板特化呼叫!

更少的代码,没有运行时开销,更安全。

这是否意味着C ++是语言的全部和全部?当然不是。您仍然必须权衡取舍。无知的人在应该编写Bash / Perl / Python脚本时会使用C ++。满足触发器要求的C ++新手将创建具有虚拟多重继承的深层嵌套类,然后才能停止它们并将其打包。在意识到这是不必要的之前,他们将使用复杂的Boost元编程。他们仍然会使用char*strcmp和宏,而不是std::string和模板。

但这无非是...观察与谁共事。没有语言可以保护您免受不称职的用户的侵害(没有,甚至没有Java)。

继续学习和使用C ++-只是不要过度设计。


18
+1代表“没有,甚至没有Java” :)
内森·奥斯曼

53
范例为+1。这是一篇很长的文章,但是C和C ++代码之间的比较令人印象深刻。
paercebal

女士们,先生们,这就是为什么lex / yacc存在的原因。同样的道理,我从未意识到c ++的某些部分会陷入相同的代码生成哲学。我将不得不再次查看它。
Spencer Rathbun 2012年

2
我已经写了很多2D渲染代码(十多年前),并且在从C移植到C ++时遇到了这个问题:如果您的扫描线是由1位像素(8个像素组成),那么如何定义像素结构?一个字节)?当扫描线由R,G和B字节(每个像素3字节)组成时?而当您有三个分别用于R,G和B的缓冲区时?您知道答案:C ++在那里无济于事,坚持使用模板将使您失去很多空间和时间优化
Walter Tross

为什么为此使用C ++中的模板?您的方法声明了基类的参数,因此从我的[C#程序员]的角度来看,您似乎可以将派生类型实例传递给基类型参数。我不懂C ++,您能解释一下吗?
弗拉德(Vlad)

79

RAII为胜利的宝贝。

严重的是,C ++中的确定性销毁使代码更清晰,更安全,而没有任何开销。


20
“C ++:唯一严重的确定性选择今天询问你的医生吧。”
凯尔·斯特兰德

2
后续行动:Rust现在是该领域的竞争者。请参阅基本的RAII示例有关Rust的析构方法的文档
凯尔·斯特兰德

1
C将具有确定性,但是需要更多工作来确保它在使用malloc内存时真正发生
Baldrickk

1
在C中,@ Baldrickk必须在使用资源的任何地方编写清理代码。在C ++中,只需在资源定义中编写一次即可。因为清理不是自动的,所以C和Java都遭受“处理后使用资源”和“泄漏资源”的错误。内存不是唯一的资源。
卡雷斯(Caleth)'18

70

使用C ++是否有令人满意的理由?

  1. 模板和STL。您需要花费很少的构建时间(以及一些可能难以理解的错误消息)来换取许多有用的抽象和省力工具,而运行时性能却没有受到明显的影响(尽管二进制足迹可能更大)。

    这需要一段时间来包装你的头左右(我花了几年的点击它之前),但一旦你这样做可以让生活很多简单。

  2. C ++中的文本处理比C语言中痛苦少几个数量级


35
+1用于文本处理,我在答案中完全忘记了。
康拉德·鲁道夫

8
嘿,我发现特别是文本处理痛苦相比,我们说的Python ..
尼尔斯·

7
Boost是我仍然使用C ++的唯一原因。
Ferruccio

33
@Nils:以1到痛苦的程度,C ++中的文本处理绝对比更现代的语言(如Python)差。只是C中的文本处理定义了痛苦中的痛苦。如果针对该特定应用程序在C和C ++之间进行选择,则C ++很容易取胜。
约翰·波德

8
我不知道为什么人们在C / C ++中的文本处理等方面有如此困难。只需使用一个库或编写自己的库即可。一旦编写了低级函数(一次痛苦),您将获得巨大的性能,紧凑的代码和更大的灵活性。是的,我将Python用于快速/肮脏的命令行实用程序,但用于认真的C / C ++生产代码。

41

是。

如果您要寻找可执行的效率,那么您可以考虑使用C或C ++,因此我将重点介绍它。

甚至在模板不常见之前,我就早在1990年代中期就开始使用C ++而不是C讨论可执行文件,这有两个很简单的原因:对象多态RAII

我已经将多态C ++对象用于各种有趣的事情。例如,我正在一个嵌入式Linux系统上工作,该系统在OMAP和XScale ARM CPU上具有帧缓冲区覆盖。两种硬件体系结构具有不同的覆盖功能,并且具有非常不同的API。我使用一个通用的虚拟“ Overlay”基类公开了理想的叠加视图,然后编写了“ OmapOverlay”和“ XScaleOverlay”类,这些类在运行时进行了适当实例化,具体取决于运行代码的体系结构。

为了简化起见,RAII的想法是您在对象的构造函数期间或对象生命周期的稍后阶段分配连接到对象的资源,并且资源在对象的析构函数中被释放或释放。在C ++中,这确实很棒,因为自动变量的对象在超出范围时会被破坏。对于同样具备C和C ++能力的人,避免C ++中的资源和内存泄漏要容易得多。您也看不到太多的C ++代码,在函数的末尾,在调用之前有一个非常常见的标签C模因,在函数块中调用free(),而goto功能块中的各个跳转到那里。

我完全意识到,您可以使用C来完成所有这些事情-它要做的工作更多,代码行更多,并且最终得到的结果更加丑陋,而且通常很难理解。X服务器内部遍历了多态性代码,可是,它很丑陋又怪异,而且经常很难追踪。

我还使用GTK +和Clutter等GNOME技术进行了大量工作,所有这些技术都是使用GObject系统以C语言编写的。GObject就像C ++对象系统一样,它的封面很漂亮,所有丑陋的内部结构都暴露在外,它通常需要六行代码来完成单行C ++方法调用所要做的工作。我目前正在写一些东西ClutterActors,尽管数学真的很有趣,但我一直在想:“在C ++中,这一切将更加简洁和可理解”。

我还常常想:“如果我用C ++而不是C编写代码,我会和妻子一起在客厅看MythBuster,而不是晚上9点坐在我的办公室。”


9
我真的可以与您在这里所说的有关,特别是1)关于RAII的观点和2)“您知道,如果我是用C ++而不是C编写的……”的想法,我做了很多嵌入式系统开发,即使该团队几乎是“ C”或“带类的C”,我还是真的鼓励RAII进行诸如中断操纵,互斥操作和跟踪/记录(特别是诸如切换I / O之类的东西)行)。您对多态帧缓冲区的描述使我想起了我在分布式系统中使用多态消息缓冲区的情况。
弧度

29

C ++与C一样快(有些东西更快,有些慢),并且它提供了更好的抽象和组织。类的工作方式与原始类型相似,从而无需记住即可使用大量代码。操作员重载和模板使编写代码的功能成为可能,如果数据表示形式发生更改,代码的功能会更好。异常可以简化错误处理。编译器可用于在编译时检查更多内容。

您为此付出的代价是一个相当讨厌的学习曲线,并且比我熟悉的大多数其他语言更容易犯一些细微的错误。

因此,我无法确定您现在正在做的事情是否值得您去学习。当然可以将Python或Perl与C结合使用,但是C ++在一个难以使用的程序包中同时提供了抽象和性能。


13
没有情况,其中C ++是比C慢,因为你总是可以使用C方式,如果它是更快(和你关心)。
杰克·艾德利

1
@JackAidley-C ++不支持限制和静态数组参数。并且除了在一个地方使用C ++样式会迫使您在其他地方使用它之外。
martinkunev

@martinkunev restrict用于排除混叠优化,因此如何使事情更快?什么是“静态数组参数”?“样式”如何影响效果?
underscore_d

1
@underscore_d限制基于对非锯齿的保证允许优化。静态数组参数使编译器假定指针参数不为NULL,并且该指针至少指向给定数量的元素;“样式”一词具有多种含义,将其置于上下文之外会改变其含义-例如,我正在谈论异常如何强制使用智能指针。
martinkunev '16

1
@martinkunev Hmm,所以我想知道静态数组参数是否使用a T (&arr)[n]std::array<T, n>- 启用与C ++模板在功能上有所不同的任何东西,因为那里没有很多信息,因此必须进一步研究这一点。这对于智能指针是有意义的,绝对是一个很好的例子。如果在平等的竞争环境中进行编码,我们将不会使用异常,因此不会产生任何潜在的成本...但是,我怀疑您可能暗示了一旦第三方库进入画面后,会有很多假设处于危险之中。
underscore_d

27

我认为C ++是1990年代的语言,是过去时代的语言。

当时的规模很大,因为它以较低的性能成本提供了更高级别的语言结构和机制。它是开发从通讯录应用程序到航空电子软件的所有工具的通用工具,这激发了OO狂潮。OOP解决了饥饿和艾滋病,是的,我责怪C ++在1990年代末试图洗脑时,我第一次开始编程任何非OO语言都不值得学习。

既然硬件已经取得了如此多的进步,并且出现了更新的现代语言,我看不到C ++对于大多数应用程序编程仍然是一个相关的选择,除了需要大量抽象的计算密集型软件(游戏,物理模拟,CAD系统等)。 )。如果您使用C编写了一个紧凑的模块化引擎,并将更高级别的应用程序逻辑委派给一种简洁的脚本语言,则甚至可以避免后者。

如果您需要精通C语言,并且需要高级使用时,请使用不宣扬封装的现代语言来完成,而您可以通过指针自由更改每个字节。


11
因此,请勿使用指针更改随机字节。这不是很难避免,不是吗?
David Thornley 2010年

11
@Blagovest:我同意您对C ++的复杂性的看法,并且我永远不会用它来代替面向对象的语言。但是尽管它很复杂,但是由于它在不同答案(抽象,资源处理,字符串处理...)中阐明的许多优点,它仍然对我而言胜过C。事实上,你已经命名了几个有效的领域,其中C ++仍然是相关的,它远远优于C.
康拉德·鲁道夫

6
@布拉戈维斯特:这就是为什么我不在黑暗的角落。用C ++抢劫比我知道的任何其他语言都容易。通过使用它,我从RAII,更好地造福字符串处理的是C,STL的类型模板类,面向对象的特性,它拥有超过C.其他优点
大卫·索恩利

24
@布拉戈维斯特:不,你没有。例如,您提到的内容不足以实现RAII,并且容器类具有的功能超出了简单的手工数据结构。如果您认为这是可能的,那么您就不会很好地学习C ++。
David Thornley 2010年

5
@Jaroslaw我看不到为什么多核计算机会把OOP付诸实践。如果您的意思是C ++,我可以看到您来自哪里。OOP是许多现代编程语言(尤其是高级语言)中的基本概念。如果以这种方式编程,那么即使C也可以是OO。它只是不像C ++ IMO那样方便。
vedosity 2010年

21

根据Linus的说法,没有:

当我第一次查看Git源代码时,有两件事让我感到奇怪:1.纯C而不是C ++。不知道为什么。请不要谈论可移植性,它是BS。

胡说八道。

C ++是一种可怕的语言。由于许多不合格的程序员使用它,使它变得更加可怕,以至于要用它产生完全和完全废话要容易得多。坦率地说,即使选择C 除了使C ++程序员不做任何事情,这本身就是使用C的巨大原因。

换句话说:C的选择是唯一明智的选择。我知道Miles Bader开玩笑地说“生气”,但这是真的。我得出的结论是,这将喜欢的项目是在C ++对C程序员的任何可能,我真的程序员 喜欢走开,让他不来搞砸任何项目我参与用。

C ++导致非常糟糕的设计选择。您总是会开始使用该语言的“不错”库功能,例如STL和Boost,以及其他一些根本的废话,它们可能会“帮助”您编程,但会导致:

  • 当它们不起作用时会产生无穷的痛苦(而且任何告诉我STL尤其是Boost稳定且可移植的人都充满了BS,甚至都不有趣)

  • 效率低下的抽象编程模型,在过去的两年中,您注意到某种抽象不是很有效,但是现在您的所有代码都依赖于周围所有漂亮的对象模型,并且如果不重写应用程序就无法修复它。

换句话说,做一个好的,高效的,系统级的和可移植的C ++的唯一方法最终将自己限制在C语言中所有基本可用的东西上。而将项目限制在C语言中,则意味着人们不会拧,这也意味着您会得到很多真正了解底层问题并且不会因任何愚蠢的“对象模型”废话而搞砸的程序员。

因此,对不起,但是对于git这样的以效率为主要目标的情况,C ++的“优势”只是一个巨大的错误。我们还激怒了看不见的人,这只是一个很大的额外优势。

如果要使用C ++编写的VCS,请使用Monotone。真。他们使用“真实数据库”。他们使用“不错的面向对象的库”。他们使用“不错的C ++抽象”。坦率地说,由于所有这些设计决定对某些CS人士来说都如此吸引人,最终结果是一团糟且难以维护的混乱。

但是我敢肯定,您比git更想要它。

      Linus

62
我认为莱纳斯不应该在这里引起争论。他的咆哮非常主观且不成熟。他确实确实有一些优点,但是它们被深深地埋藏(在“废话”和废话之下),以至于很难找到。
康拉德·鲁道夫

19
哈哈,那是一个很好的笑声。我从不想见到这个家伙。
Felix Dombek 2010年

30
莱纳斯让我想起了一个非常有才华的屋顶工,他从未悬挂过石板,而是称其为三色紫罗兰,因为他们使用螺钉而不是钉子。
鲍勃·墨菲

8
莱纳斯(Linus)提出了一点,但表达得过于苛刻,以至于无法认真对待。
Blagovest Buyukliev

39
我同意@Daniel的观点,如果有人可以谈论突破硬件的界限,那就是约翰·卡马克(John Carmack)是厄运,地震和其他游戏的创造者,也是ID软件的创始人。几个月前,他在推特上写了关于c和c ++的文章:“ IMO,好的C ++代码比好的C代码要好,但是坏的C ++比坏的C代码差很多,甚至更糟。” twitter.com/#!/ID_AA_Carmack/status/26560399301
Onema 2010年

18

我认为没有任何令人信服的理由使用C ++。如果要进行OO编程,则可以改用Python并用C编写需要快速性能的部分。

编辑:还有其他语言可以很好地与C交互,因此,如果您不喜欢Python,则可以选择其他语言。


3
嵌入式开发呢?Python并不总是可用,在经过一定处理能力的设备上,C和编写良好的C ++之间的速度差异可以忽略不计。当然,我想C ++编译器也不总是可用……
James 2010年

6
@James“写得很好的C ++”-有个问题:(
dss539 2010年

5
我同意这个答案,使用python做高级,因为您将以大约3倍的速度编写它,进行概要分析,然后通过用C / C ++替换瓶颈来释放瓶颈。说“用C ++代码代替瓶颈”是多余的,因为您不会对需要快速处理的代码进行任何高级处理,因为它将是低级代码。有一件事:我不知道如何将c ++与python:/进行接口。但是就屏幕前的时间和效率而言,我认为这是最好的解决方案,因为大多数C ++代码将很快实现!
jokoon 2010年

8
去一家大型金融公司工作,并在一个庞大的Python分布式团队中建立一个复杂的财务系统,看看您的喜好如何。经验将告诉您:a)类型安全的优点,b)节省您的屁股的编译器的优点,c)Python允许noobs编写的LUDICROUS代码。人们说用C ++踩脚很容易->某些python东西虽然有用,但有些疯狂。现在,我宁愿使用C ++进行工作……
MrFox 2012年

1
@suslik:哇,我很震惊,实际上任何人都将python用于这种系统。对于不好的noob python代码,我同意你的看法;我自己看过
拉里·科尔曼

13

有使用C ++的理由吗?当然。

有些人可能会更喜欢使用C ++,而不是其他选项。询问是否有理由使用C ++就像询问为什么我们需要数百种口味的冰淇淋。并非每个人都喜欢简单地坚持使用香草。

如果开发人员已经对C ++很有能力,那么他们面临的问题可能不是“为什么使用它?”,而是“为什么不使用它”。SO中似乎正在发生这种流行的反C ++事情,但是不管您是否相信,并不是每个人都对此表示赞同。有些人可能比其他语言更喜欢C ++。

是否需要将C ++ 用于应用程序?当然不是。但是,对于其他任何语言,也可以询问相同的确切问题。在极少数情况下,需要为应用程序使用特定语言。


12

我只是从C切换到C ++,即使您不需要模板和OOP,我也认为收益是可观的。

  • 更好的内存管理
  • 加强型系统
  • 更好的标准库
  • 命名空间
  • 等等

8

令我惊讶的是,还没有人提到它,但是C ++向我们介绍了reference,它几乎解决了指针的所有问题和陷阱:

void ModifyVar(int& var)
{
    var = 5;
}

int test = 4;
ModifyVar(test);

代替:

void ModifyVar(int * var)
{
    *var = 5;
}

int test = 4;
ModifyVar(&test);

也更加安全,容易...而且没有价值传递的开销。


3
也没有那么灵活。引用(C ++风格)擅长于简化也具有指针的语言中的某些常见构造,但它们远不能替代指针,甚至不好笑。而且您的示例并不是一个很好的参考案例。
Ben Voigt 2010年

3
@本:那么请您解释一下为什么这是一个不好的例子?
内森·奥斯曼

6
@George:因为什么都没有改变,除了短了两个('em')字符?它没有解决任何问题,没有强调任何陷阱,甚至没有做任何很酷的事情,例如延长临时变量的寿命(引用很擅长)。
Ben Voigt 2010年

@Ben:您忘记了什么-参考始终有效。指针可以指向任何内容(包括NULL),如果操作不正确,则可能导致各种内存错误。引用永远不能为NULL,指向的地址也永远不能更改。
内森·奥斯曼

5
@乔治:“引用总是有效的”完全是错误的。如果您需要一个示例,我将举一个例子,但我希望您有足够的专业知识,已经意识到这一点。我也不是在谈论使用无效指针形成无效引用。使用指针的函数需要文档说明参数的前提条件。但实际上,所有函数都需要该级别的文档,因此称其为指针罢工是荒谬的。
Ben Voigt 2010年

5

通常在何处以及为什么:

  • 熟识
  • 所需的语言功能
  • 您要使用的特定库
  • 性能要求

对于服务器端编程,您通常可以从编译或解释的多种不同语言中进行选择。通常,语言的选择取决于您或您的团队在哪个平台上最有效。或者,如果您还没有团队,那就是市场上技能的可用性。

附带说明一下,我真的不理解基于性能来决定使用C / C ++(仅),因为许多脚本语言都可以用C / C ++进行扩展。您将获得快速开发语言的好处以及将慢速部分迁移到C / C ++扩展的能力。当然,如果您在进行系统编程时每个操作都很重要,那是可以理解的,但是在大多数应用程序开发中,我是无法理解的。


2
熟悉是第一大原因,我很惊讶您是第一个提到它的人。
Paul Butcher 2010年

4

C ++ vs Python vs Perl很难判断。这取决于项目和要求。

C ++从很早以前就有大量的实用程序,可以在许多平台上运行。但是开始遍历流只是将String传递给Integer并反向进行是很痛苦的。

另一方面,C ++对库的依赖项处理得很糟糕。一旦在GCC X或VC ++ Y中进行了编译,就无法依靠代码将在这些工具的下一版本中运行。在Windows上也一样,在Unix上也一样。

Perl从Unix世界获得了强大的功能,但特别是作为正则表达式工具。这是大多数时候使用的。Perl加上一些非常认真的工具,甚至Java也无法以正常方式做到这一点(请查看如何将文件上传到Web服务器),Perl就是“做到这一点”。

Python是简单,灵活和动态的语言。如此简单,您可以将整数发送给函数,脚本需要字符串,但可以得到结果!虽然出乎意料,但却是结果。因此程序员需要非常谨慎。空闲提供了一些调试功能,但是当您将TELNET连接到系统上,或者将SSH降低了三个级别时,如果您想查找问题,则调试器将不会在那里站着。但是,它可以快速完成一些出色的数学工作。

Java是一个由流行词,外来技术和流行词组成的生态系统,当您只想将文件上传到Web服务器时,就会发现只有在服务器具有JSP的情况下,您才能做到这一点。如果要调用系统库或诸如监视之类的系统功能,您会发现必须进行大量挖掘。也许是到达JNI并确定...然后您想...“为什么,上帝?”

除此之外,Java是用于商务套件和多线程的出色工具,我非常喜欢它。

快速编写程序并向您的简历显示“哦,我也知道技术”,而您想要成为的老板也很惊讶!即使,可能也不需要该技术...(好吧,伙计们,我讨厌Spring框架 ....)


1
las,您必须考虑到Python具有版本依赖性-尤其是一旦您迁移到与perl ..相同的Python 3后,还是有人不愿意迁移到Perl 6?一切都具有令人讨厌的依赖关系:(
gbjbaanb 2012年

3

选择语言时要牢记的一点是,使用该语言会带来什么好处,以及花费多长时间才能获得该语言。

像python和perl这样的语言之间的主要思想是,以更少的人工时间来做更多的事情,但是要花更多的cpu时间。实际上,您将花费更多的时间来编码python或perl脚本,而不是将其执行,但是您明白我的意思。

C / C ++的优点是它们速度很快,但是要花语法和强大的键入功能:您必须自己做很多事情,以使计算机不必在编译时选择它。

编写代码时,某些行比其他行要运行得多,而这些行会带来问题。另一方面,其余所有代码(您花了很多时间编写的代码)的执行频率要低得多。您可能已经听过,但这是臭名昭著的80/20规则,您将无法绕过该规则。

解决此问题的方法是使用一种更简单的语言(通过更简单的语言,我的意思是对开发人员更友好:更少的键入,懒惰的解释,大量预先存在的例程和内容,等等)来完成所有代码。

与使用C或C ++进行处理相比,这样做的速度如此之快,这会花费更多的脑部疼痛。

您的程序速度很慢,但是使用事件探查器,您可以隔离运行了80%的时间的零件,然后使用C或C ++进行处理。

通过以这种方式进行编程,您节省了很多时间,并且程序高效,快速,泄漏内存的机会更少,并节省了时间。

脚本语言被设计为在开发者方面,但是优化仍然是可能的。当然,您可以是设计模式魔术师,STL伏都教徒,甚至是轻率的战士,甚至还可以是Haskell的和尚。但是语言使我们与计算机对话,语言不是让我们成为计算机!




0

对于这样形成的所有问题,实际上只有一个答案。使用技术X而不是技术Y(其中X和Y大致处于同一水平(就像几乎所有当代编程语言一样))的最佳原因是因为您已经知道X而不知道Y。

(但是在Haskell到达之后,没有理由使用其他任何东西)


0

一点都不。如果您不需要性能,并且有一个库可以使用其他语言,则不必理会C / C ++。如今,我只针对无法(轻松地)运行语言的嵌入式系统这样做。有时我使用C是因为我正在编写一个插件,但实际上没有。

但是,我不会使用Python,Perl等来避免使用C。我的偏好实际上是C#,因为我喜欢一个好的库(这是.NET的强项),而且我喜欢静态类型的语言。是一个很好的选择。但实际上HaskellOCamlDML等都很好。


7
你错过了重点。
马特·乔纳

@Matt Joiner:我确定没有。我错过了什么?

问题是关于不使用C ++。
马特·乔纳

@马特·乔纳(Matt Joiner):嗯,从另一个角度看,我看到了有人问。但似乎我也回答了(我说不要打扰,我使用的替代方法是)

我几乎想因为C#而
对此表示反对
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.