169

As a Linux (server side) developer, I don't know where and why should I use C++.

When I'm going for performance, the first and last choice is C.

When "performance" isn't the main issue, programming languages like Perl and Python would be good choices.

Almost all open source applications I know in this area have been written in C, Perl, Python, Bash script, AWK or even PHP, but no one uses C++.

I'm not discussing other areas like GUI or web applications, I'm just talking about Linux, CLI and daemons.

Is there any satisfactory reason to use C++?

Omid
  • 103
  • 3
Ehsan
  • 853
  • 3
  • 8
  • 9
  • I presume "server-side" in this context means headless services, and not the kernel itself? – sdg Dec 22 '10 at 15:35
  • Yes, just about CLI shell apps. – Ehsan Dec 22 '10 at 16:39
  • 47
    So something that can be done using C, perl and python together can be done using C++ only. And you are asking why to use C++? – Manoj R Dec 23 '10 at 05:37
  • 39
    « When I'm going to performance, the first and last choice is C. » yeah sure :D This is an unproven, and trivially wrong assertion. – deadalnix Aug 02 '11 at 17:06
  • 16
    @deadalnix: I wouldn't say that. C++ has complex rules that might backfire on optimizer, because it's not allowed to do some things. And it's super easy to step into invisible performance killers. It's pretty much axiomatic, and therefore true :D Still in reality C++ code will sometimes be faster because you'll be using more effective algorithms and data structures, and noone actually optimizes C code anyway. So when done correctly, C++ is safer and more effective C, and you should pick C++ over C when there are no compatibility problems, or requirement for 100% availability software. – Coder Dec 18 '11 at 21:43
  • 4
    The best reason, not considered in the posted answers, directly relates to OP's question. DEPENDANCIES!!!!, Not that your average system lacks the c++ libs, but an embedded system might not have them available. The only way to to get your program in every system, is to write your program in regular C. Everything else is just debating why you should, or less represented, should not use C++. None of that addresses why C++ is not used more often, and regardless of merit, the reason is dependencies.... O and also Linus's famous c++ rant. – J. M. Becker Apr 02 '13 at 22:01
  • [According to Facebook](https://github.com/facebook/hiphop-php), maybe. – LennyProgrammers Dec 22 '10 at 14:01
  • 5
    I only consider C++ because of STL. – dan_waterworth Dec 22 '10 at 16:29
  • 1
    I learned C++, because the best job offer I received required it. –  Dec 22 '10 at 22:47
  • 1
    I found C++ sometimes better for command-line utilities than python because it's a lot faster in both startup time (if the binary has relatively small number of libraries, but it may become similar to python if it's linking a lot) and processing time (e.g. when there are hundreds of millions of records to process). However for lightweight tasks or generation of web-pages python is definitely better. – Andrew Smith Jul 24 '15 at 16:42
  • 3
    @TechZilla: Uhm, why should I want to get my program into _every_ system? For what definition of "every" is that? Oh, just recently I did some C code for Arduino. Guess what: Some dependencies per the standard were not there. Your argument is therefore unclear and/or BS. – phresnel Jul 30 '15 at 08:54
  • 1
    @phresnel: You're asking why should *you* want something? Why should I need to tell you what you'd want?! As for your feckless post-modernist deconstruction, "every" was clearly referring to GNU/Linux Systems. OF which can be expected to support POSIX C. Arduino is a microcontroller, the expectation would no longer be reasonable. – J. M. Becker Jul 31 '15 at 21:35
  • 1
    @TechZilla: Because "every system" is superhero rockstar BS. It's impossible, unrealistic, inprofitable and unresearched. That's why I asked for the "why". And: If "GNU/Linux Systems" was "clear" or obvious, can you tell me where you _clarified_ that? Clearly, you said "every system", not more, not less. Be more precise, and refrain from reacting like an impudent kid that uses terminology out of its control. – phresnel Aug 03 '15 at 08:03
  • @phresnel: Only your own deconstructed definition is nonsense, once you add the context of the OP's question ... "As a Linux (server side) developer" . Every clearly means every "Linux" system, and yea consider that researched, check kernel.org for my sources. Amazing how your sociology class teaches you to stop understanding how the working public communicates. – J. M. Becker Aug 03 '15 at 23:17
  • @TechZilla: Unfortunately, your line of argumentation becomes void if you add the second part of the statement you quoted: "As a Linux (server side) developer, **I don't know where and why should I use C++.**". And, what is a "deconstructed definition"? And, why are trying to impose a badass dude on me? I bet in Real Life you're a friendly dude that couldn't kill a fly. – phresnel Aug 04 '15 at 07:50
  • @phresnel, I never stated that I could answer the OPs question, this was/is a comment and not an answer. So now we've now concluded my mere consideration, may be reasonable depending on individual circumstance? Your interpretation of who you believe me to be, is irrelevant to my original consideration, I never asked others to share my concerns. I simply mentioned a concern I had, which was not represented... It was you who had the problem – J. M. Becker Aug 05 '15 at 17:50
  • 2
    @TechZilla: It's just the comment sections. You talked unsolicitedly, so accept that others will, too. Your initial comment stated something about "every system". I raised my concerns that this is unrealistic. And you basically agreed with me by refining your original comment to the GNU/Linux subset of "every system" afterwards; note: **subset**. Even tho you claim that was "clear", it actually wasn't. Yes, I had a problem: That you have problems with being precise, and then claim "clarity" where there isn't any. But we agree on laying this down, now. Let's drink a beer when we meet in RL :) – phresnel Aug 06 '15 at 10:01
  • Except that you didn't reject the actual thought process which explains the Pro-C behavior we sometimes encounter, you took my words out of context when they clearly were in relation to OP. The purpose was to essentially prove clarity itself is unrealistic, and thus my prior commentary meaningless. Did you actually misread my commentary?, I don't think so, I think you purposely misused language to invalidate and dismiss a conclusion you found unfavorable. Marxists and Post-modernists don't have beers, we dislike each other for the correct reason. – J. M. Becker Aug 06 '15 at 19:55
  • 1
    You can use C++ as C-with-sugar and then the reason is obvious (you want to use the sugar). – user253751 Nov 06 '16 at 22:31

18 Answers18

313

When I'm going to performance, the first and last choice is C.

And that’s where you should back up. Now, I cannot, at all, speak for server development. Perhaps there is indeed no compelling reason to prefer C++ over the alternatives.

But generally speaking, the reason to use C++ rather than other languages is indeed performance. The reason for that is that C++ offers a means of abstraction that has, unlike all other languages that I know, no performance overhead at runtime.

This allows writing very efficient code that still has a very high abstraction level.

Consider the usual abstractions: virtual functions, function pointers, and the PIMPL idiom. All of these rely on indirection that is at runtime resolved by pointer arithmetic. In other words, it incurs a performance cost (however small that may be).

C++, on the other hand, offers an indirection mechanism that incurs no (performance) cost: templates. (This advantage is paid for with a (sometimes hugely) increased compile time.)

Consider the example of a generic sort function.

In C, the function qsort takes a function pointer that implements the logic by which elements are ordered relative to one another. Java’s Arrays.sort function comes in several variants; one of them sorts arbitrary objects and requires a Comparator object be passed to it that works much like the function pointer in C’s qsort. But there are several more overloads for the “native” Java types. And each of them has an own copy of the sort method – a horrible code duplication.

Java illustrates a general dichotomy here: either you have code duplication or you incur a runtime overhead.

In C++, the sort function works much like qsort in C, with one small but fundamental difference: the comparator that is passed into the function is a template parameter. That means that its call can be inlined. No indirection is necessary to compare two objects. In a tight loop (as is the case here) this can actually make a substantial difference.

Not surprisingly, the C++ sort function outperforms C’s sort even if the underlying algorithm is the same. This is especially noticeable when the actual comparison logic is cheap.

Now, I am not saying that C++ is a priori more efficient than C (or other languages), nor that it a priori offers a higher abstraction. What it does offer is an abstraction that is very high and incredibly cheap at the same time so that you often don’t need to choose between efficient and reusable code.

Konrad Rudolph
  • 13,059
  • 4
  • 55
  • 75
  • 16
    I do now know enough about C++ to know whether you are spot on or wrong. But also want to add you only received 1 downvote so relax. This is the internet and downvotes happen. Great answer though if its technically sound! – Chris Dec 22 '10 at 17:51
  • 3
    Actually, modern compilers such as MSVC are capable of the nifty trick of cross-module inlining. – Manuel Dec 22 '10 at 19:38
  • 1
    I wonder about Exceptions, do they come with overhead? – Nils Dec 22 '10 at 20:52
  • 48
    *no performance overhead at runtime* - that's not always true. If you look at STL vector implementations you will see that they don't take the advantage of using realloc() (they can't because of pointers, long story) whereas all higher-level languages that I know can and do use realloc() in vector impl's. This is just one example that it's not that obvious and all black-and-white. – mojuba Dec 22 '10 at 20:55
  • 1
    @Manuel: that’s indeed a nifty trick but this optimization (applied to function pointer inlining) is highly complex (it basically requires a flow analysis to show that the pointer never changes) and cannot in general be relied on. I’d be interested in numbers, though. Do you have any? – Konrad Rudolph Dec 22 '10 at 21:04
  • 11
    @mojuba: they can’t because of *destructors*. Apart from that, please tell me which higher-level languages do use realloc. I don’t know of any that do. I know that most don’t – but then, comparing with managed memory is always difficult. A custom allocator can in fact help, though a custom allocator cannot take advantage of `realloc` either. What it *can* do, though, is emulate `realloc` on a higher level. In that way, they can achieve a very similar behaviour to garbage collected storage (if that’s what you were referring to). – Konrad Rudolph Dec 22 '10 at 21:07
  • 5
    upvoted, though I would suggest that Ocaml is an example of a language that can get very close to C++ performance while still allowing highlevel abstractions (though these are generally different abstractions from those available in C++ - things like function composition, functors, etc.) as well as well as niceties like type inference, garbage collection and even stronger type safety than what's available in C++. – aneccodeal Dec 22 '10 at 21:55
  • 6
    > "C++, on the other hand, offers an indirection mechanism that incurs no (performance) cost: templates." obviously you haven't heard of the instruction cache. – jsz Dec 22 '10 at 23:26
  • 1
    @mojuba, I'm not sure, but I think C++0x will be able to address mojuba's concern. I think I read that is_pod will be available, and in the case of a POD type, you could use realloc safely. – Neil G Dec 22 '10 at 23:39
  • 3
    @Neil G, but that would require a change to `std::allocator`. It would need a `reallocate` function that container classes can take advantage of. – Charles Salvia Dec 23 '10 at 00:18
  • @Charles, Yes, good point. In fact, that's a much better solution. reallocate could use C++0x's move semantics in the case that the type is non-POD and the new block is in a different place. – Neil G Dec 23 '10 at 03:55
  • 5
    Templates can be prone to bloat, which is a big run-time cost. It's not just that the program takes longer to load, but also that a smaller proportion fits into the highest cache levels at any one time. A well written template may be a typesafe thin wrapper around non-typesafe underlying code, but then you re-introduce more obvious abstraction overheads. Templates are worthwhile primarily for type safety reasons - not high-performance abstraction reasons - though there are exceptions to that. –  Dec 23 '10 at 08:36
  • 3
    @Neil G: unfortunately it's not only POD vs non-POD. The problem is that in C++ a vector element can contain pointers to locations that potentially may be affected by realloc(). The only way of keeping these pointers up to date is copying elements (during resizing of a vector), and calling copy ctors. There is no way in C++ for the vector implementation to know if a vector element in fact contains such pointers or not. – mojuba Dec 23 '10 at 09:59
  • @Konrad Rudolph: please see my ohter answer above, but actually you may be right regarding garbage collectors: I'm not sure they can handle reallocations of pointers. But then it depends on the GC. Some very simple ref-counted GC's can do fine (PHP comes to mind). – mojuba Dec 23 '10 at 10:05
  • 20
    @Jaroslaw, @Steve: but the same (= code bloat, instruction cache misses) is true for hand-optimized code which is adapted for each data type (see Java’s various `Arrays.sort` implementations). Only you lose the advantage of high abstraction. This isn’t a specific disadvantage of templates, it’s a disadvantage of code duplication in general. Furthermore, this tends not to matter since in tight loops, it’s usually always the same code that is loaded. – Konrad Rudolph Dec 23 '10 at 10:20
  • 13
    @Steve314: Konrad has explained one very common case where template improve performance. How can you say this isn't usually the case?? Enter template-meta programming, where very complicated code often compiles down to a few machine instructions. If you want to see what TMP can do, have a look at http://www.templog.org, which boils down a complex logging statement to nothing (tested on VC, with logging disabled) or one `if` to check whether a log message should be shown. Show me one other language where syntactic elegance combines with tremendous efficiency in such a great way. – sbi Dec 23 '10 at 11:11
  • @mojuba, yes, and why isn't it possible for a reallocate function to call the copy constructor (or move constructor in C++0x)? – Neil G Dec 23 '10 at 11:59
  • 2
    @Neil: the problem is that `realloc` either reuses the old memory, or returns a new pointer and *scraps* the old memory. Without calling any destructors, of course. This gives the calling code *no* chance to call destructors: if it does so before calling `realloc`, it might destroy memory prematurely. If it does so after calling `realloc`, then the destructor calls are executed on freed memory => UB. – Konrad Rudolph Dec 23 '10 at 12:42
  • @konrad, yes, but we're talking about adding a reallocate function to std::allocator. That function could easily invoke the move constructor if necessary. – Neil G Dec 23 '10 at 13:02
  • 19
    @Jaroslaw: the funny thing about the instruction cache is that *it is a cache*. That is, it does not try to store *everything*, only *recently used code*. Templates might generate lots of similar code for different types (a `vector.push_back` for `vector`, and another for `vector`, but while working with a `vector`, there is little reason why the `vector` code would be in the instruction cache. So I don't see how that really matters. Every *individual* template instantiation is highly optimized and typically *more* compact than generic catch-all implementations – jalf Dec 23 '10 at 14:42
  • 8
    ... because much of the code can be inlined or optimized away. A `sort` for integers may be able to avoid generating code for a lot of special cases that are only relevant for other types, so while there may be a lot of code paths, each individual code path is certainly not bloated just because you use templates. Often, the opposite is the case. – jalf Dec 23 '10 at 14:44
  • 2
    @sbi - template metaprogramming in C++ is ugly and fragile. It is also powerful, but that only overrides the ugliness and fragility in a few special cases. There are some big wins for C++ templates, and sort certainly stands out - but even that can be bloat prone at times. If you sort lots of vectors of basic types you win - but if you sort lots of vectors of different classes you probably lose. Typesafe container classes need a lot of care to avoid bloat. Last I checked, standard container implementations generally don't bother with bloat-avoiding measures. –  Dec 24 '10 at 04:11
  • 2
    @jalf - a lot of data in many of my applications is in database-table-like form - containers of record-like items. Sometimes hundreds of different record-like types, and inner loops generally do work with several tables at once. In short, there are good reasons to believe that I can benefit by using the same underlying code to search/insert/whatever in a container irrespective of the record-type it contains - it very often is already in the cache. I use my own container library in part because it *is* a thin typesafe wrapper over non-template code, and saved on bloat in the past. –  Dec 24 '10 at 04:17
  • 2
    Of course. It depends on the workload. Show me an implementation strategy that is optimal in *all* cases. I'm just saying that templates do not *automatically* imply bloat. It depends on how they're used, and in some workloads, templates might lead to *less* bloated code than a single general implementation. – jalf Dec 24 '10 at 08:57
  • 30
    @Steve314: What you call "bloat" is what is done manually for C and Java. In C++, it can be automated, and compilers can be as smart as vendors dare to make them to avoid bloat. If I have to decide between either being slow (as in C) or use duplicated code (as in Java), having the compiler doing the duplication (and maybe being smart about it) seems pretty good, no? – sbi Dec 27 '10 at 23:27
  • 1
    What about Ada's generic packages (and other generics) --- I think they're handled at compile-time in a similarly efficient way. – JasonFruit Jul 11 '11 at 11:17
  • 1
    @Jason Indeed, the same that counts for C++ also counts for Ada, D, Ocaml and perhaps a few other oddball languages. – Konrad Rudolph Jul 11 '11 at 12:09
  • 2
    One problem with writing high-performance C++ code as opposed to C (which I don't see anyone mentioning) is that in C it is comparatively easy to get a rough idea of what code the compiler is going to generate. In C++ this is in general very difficult, mainly due to RAII. – JesperE Sep 28 '12 at 16:20
  • 7
    @JesperE It’s even easier in assembly. It’s true – but that’s not an argument. – Konrad Rudolph Sep 28 '12 at 17:15
  • 1
    @KonradRudolph Why not? It affects how easy it is to understand what kind of code is going to be executed. Doesn't that matter? – JesperE Sep 28 '12 at 17:45
  • 7
    @JesperE To some extent. However, the idea here seems to be that C++ requires *more* understanding to produce equally well-performing code, and I don’t believe that: sure, if you write high-level code without understanding performance implications then chances are this will be slow(er). But all C++ does is tip the balance in favour of efficient abstraction. It doesn’t change the fact that in order to write a given system (whether in C or C++) you need to understand it. To get efficiency in C, you’d write complicated low-level code. – Konrad Rudolph Sep 28 '12 at 17:50
  • 1
    C++ does more than just "tips the balance". C is closer to the metal, while C++ provides better abstractions. When you want to squeeze the last cycle out of the hardware, C++ complicates things by hiding many things behind templates and other abstractions. In some cases that may still be beneficial for performance, but in other cases not. – JesperE Sep 28 '12 at 18:11
  • 14
    @JesperE That is simply not a correct distinction. *If* those abstractions get in the way, simply don’t use them. But in cases where they can be used efficiently, C++ allows writing simpler code than C would. – Konrad Rudolph Sep 28 '12 at 18:23
  • 3
    JesperE, for a competence c++ programmer, they know what kind of c++ codes would bring them peformance penalty when compare to c solution.The difference between competence c programmers and competence c++ programmers is like the following post(ttsiodras post it) said, competence c++ programmers know how to write no run-time overhead, more safety and less codes when compare to c programmers, you will never know how could this be done if you don't study c++ carefully.Stop acting like a FUD programmer like linus who criticize c++ without trying to understand c++ – StereoMatching Apr 20 '13 at 12:56
  • @StereoMatching Tone it down a bit please, this is a Q&A for professional software developers, not really the best place for flame wars and rants. – yannis Apr 22 '13 at 06:17
  • 1
    Bjarne Stroustrup examines the efficiency of C `qsort()` vs. C++ `std::sort()` in some detail in [part 3 of _Five Popular Myths about C++_](https://isocpp.org/blog/2014/12/myths-3). Turns out C++ is going to be quite a bit more efficient. – Rob K Jan 05 '15 at 20:44
  • Implicit behavior makes the code harder to track and understand. It can also lead to bugs, unexpected behavior, etc. While C++ does a lot for you, this is not always beneficial. It's great to have abstractions but not leaky abstractions (and for performance, abstractions tend to leak). qsort may be slower than std::sort, but not that much slower and it doesn't really matter because often you'll end up writing your own anyway. If we consider standard library problems as drawbacks of the language, then I would mention std::list. – martinkunev Oct 30 '15 at 19:20
  • 4
    @martinkunev I agree with some things you’ve said, except that it simply doesn’t apply here. *Every* function call obviously represents an abstraction, and leaky abstractions are fundamentally unavoidable. Regarding `sort`, I’ve encountered situations where the difference was non-negligible, and your suggestion to write your own general-purpose `sort` function is utterly impractical: writing a fine-tuned `sort` is *really, really* hard. You don’t do this. You use a proven implementation. — And yes, `std::list` is terrible. But the standard library algorithms aren’t. – Konrad Rudolph Oct 31 '15 at 16:37
  • More of a philosophical than technical debate. Unless you minimize leaky abstractions, some'll end up causing more problems than they solve. You may save time with C++ std. or you may waste time until you realize you've made a bad decision. Then too much may already depend on your choices. When C++ std doesn't do what you need, you'll have to write (or modify existing) code anyway. Writing a general-purpose fine-tuned sort is indeed really hard. That's a reason to use domain knowledge to tune sorting for what is needed in the project. Anyway, I don't think std is enough of a reason to use C++. – martinkunev Nov 02 '15 at 13:08
  • 5
    @martinkunev If you don’t think it’s a strong enough reason then you probably work in a domain where that’s true. If, however, you work in a domain where a strong and finely tuned algorithms library is necessary, believe me, this *is* a good enough reason — I work in bioinformatics, and it’s crucial here. – Konrad Rudolph Nov 02 '15 at 13:51
  • An interesting case for Java where the JIT can inline small function calls. Is it smart enough these days to recognize that the comparator parameter is always the same so it can be inlined? – Thorbjørn Ravn Andersen Sep 05 '18 at 11:20
  • @ThorbjørnRavnAndersen It *isn’t* always the same: it’s only the same for a given call to the `sort` method. But if the user calls `sort` again, even with the same generic types (which are type-erased anyway), they might pass a different comparator. – Konrad Rudolph Sep 05 '18 at 13:58
172

I see way too many C programmers that hate C++. It took me quite some time (years) to slowly understand what is good and what is bad about it. I think the best way to phrase it is this:

Less code, no run-time overhead, more safety.

The less code we write, the better. This quickly becomes clear in all engineers that strive for excellence. You fix a bug in one place, not many - you express an algorithm once, and re-use it in many places, etc. Greeks even have a saying, traced back to the ancient Spartans: "to say something in less words, means that you are wise about it". And the fact of the matter, is that when used correctly, C++ allows you to express yourself in far less code than C, without costing runtime speed, while being more safe (i.e. catching more errors at compile-time) than C is.

Here's a simplified example from my renderer: When interpolating pixel values across a triangle's scanline. I have to start from an X coordinate x1, and reach an X coordinate x2 (from the left to the right side of a triangle). And across each step, across each pixel I pass over, I have to interpolate values.

When I interpolate the ambient light that reaches the pixel:

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

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

When I interpolate the color (called "Gouraud" shading, where the "red", "green" and "blue" fields are interpolated by a step value at each pixel):

  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;

When I render in "Phong" shading, I no longer interpolate an intensity (ambientLight) or a color (red/green/blue) - I interpolate a normal vector (nx, ny, nz) and at each step, I have to re-calculate the lighting equation, based on the interpolated normal vector:

  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;

Now, the first instinct of C programmers would be "heck, write three functions that interpolate the values, and call them depending on the set mode". First of all, this means that I have a type problem - what do I work with? Are my pixels PixelDataAmbient? PixelDataGouraud? PixelDataPhong? Oh, wait, the efficient C programmer says, use a union!

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

..and then, you have a function...

  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;
          }
...

Do you feel the chaos slipping in?

First of all, one typo is all that is needed to crash my code, since the compiler will never stop me in the "Gouraud" section of the function, to actually access the ".a." (ambient) values. A bug not caught by the C type system (that is, during compilation), means a bug that manifests at run-time, and will require debugging. Did you notice that I am accessing left.a.green in the calculation of "dgreen"? The compiler surely didn't tell you so.

Then, there is repetition everywhere - the for loop is there for as many times as there are rendering modes, we keep doing "right minus left divided by steps". Ugly, and error-prone. Did you notice I compare using "i" in the Gouraud loop, when I should have used "j"? The compiler is again, silent.

What about the if/else/ ladder for the modes? What if I add a new rendering mode, in three weeks? Will I remember to handle the new mode in all the "if mode==" in all my code?

Now compare the above ugliness, with this set of C++ structs and a template function:

  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;
      }
  }

Now look at this. We no longer make a union type-soup: we have specific types per each mode. They re-use their common stuff (the "x" field) by inheriting from a base class (CommonPixelData). And the template makes the compiler CREATE (that is, code-generate) the three different functions we would have written ourselves in C, but at the same time, being very strict about the types!

Our loop in the template cannot goof and access invalid fields - the compiler will bark if we do.

The template performs the common work (the loop, increasing by "step" in each time), and can do so in a manner that simply CAN'T cause runtime errors. The interpolation per type (AmbientPixelData, GouraudPixelData, PhongPixelData) is done with the operator+=() that we will add in the structs - which basically dictate how each type is interpolated.

And do you see what we did with WorkOnPixel<T>? We want to do different work per type? We simply call a template specialization:

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


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

That is - the function to call, is decided based on the type. At compile-time!

To rephrase it again:

  1. we minimize the code (via the template), re-using common parts,
  2. we don't use ugly hacks, we keep a strict type system, so that the compiler can check us at all times.
  3. and best of all: none of what we did has ANY runtime impact. This code will run JUST as fast as the equivalent C code - in fact, if the C code was using function pointers to call the various WorkOnPixel versions, the C++ code will be FASTER than C, because the compiler will inline the type-specific WorkOnPixel template specialization call!

Less code, no run-time overhead, more safety.

Does this mean that C++ is the be-all and end-all of languages? Of course not. You still have to measure trade-offs. Ignorant people will use C++ when they should have written a Bash/Perl/Python script. Trigger-happy C++ newbies will create deep nested classes with virtual multiple inheritance before you can stop them and send them packing. They will use complex Boost meta-programming before realizing that this is not necessary. They will STILL use char*, strcmp and macros, instead of std::string and templates.

But this says nothing more than... watch who you work with. There is no language to shield you from incompetent users (no, not even Java).

Keep studying and using C++ - just don't overdesign.

ttsiodras
  • 201
  • 1
  • 2
  • 4
  • 20
    +1 for "no, not even Java" :) – Nathan Osman Dec 27 '10 at 05:32
  • 54
    +1 for the example. It was a long post, but the comparison between C and C++ code is impressive. – paercebal May 29 '11 at 13:17
  • And this, ladies and gentlemen, is why lex/yacc exists. Same reasoning, I never realized parts of c++ fell into the same code generation philosophy. I'll have to look at it again sometime. – Spencer Rathbun Sep 28 '12 at 18:41
  • 2
    I have written lots of 2D rendering code (more than a decade ago), and ran into this problem while porting from C to C++: how do you define a pixel struct, if your scanline is made of 1-bit pixels (8 pixels in a byte)? And when your scanline is made of R, G and B bytes (3 bytes per pixel)? And when you have three separate buffers for R, G and B? You know the answer: C++ is of no help there, and insisting on using templates will make you loose a lot of space and time optimizations – Walter Tross Oct 29 '13 at 00:39
  • Why do you use templates in C++ for this? Your method declares a parameter of the base class so from my [C# programmer] point of view it looks like you could just pass derived-type instance to base-type parameter. I don't know C++, could you explain please? – Vlad Mar 13 '16 at 14:42
  • You can solve many of your C problems by writing better C: "one typo is all that is needed to crash my code" - you can create 3 structs with CommonPixelData as their first member and cast the passed pointer; "in the Gouraud loop, when I should have used "j"" - if you put the variables i and j in the blocks they ought to be, the compiler will complain; "What about the if/else/ ladder for the modes" - use switch – martinkunev Apr 22 '16 at 07:14
  • @Vlad The template just merely declares a PixelData type; this is not the base class CommonPixelData. The class template and function template specialisations WorkOnPixel directly use the final/derived classes. The inheritance is not even needed to make it work: in fact the code would even work without declaring the base class, you could decide to duplicate the x member in each class. – Johan Boulé Aug 01 '16 at 16:06
  • @WalterTross: clearly beating a dead horse here, but 99% all the problems you're describing are solvable via having a template using struct Scanline as a template parameter (and then, pixel access can be abstracted too quite easily). And FWIW: it is not 2D, but these days even NVIDIA designs their chips while citing C++ standard to each other (was explicitly said during CPPCON17 by Olivier Giroux). – No-Bugs Hare Jul 16 '18 at 15:31
81

RAII for the win baby.

Seriously, deterministic destruction in C++ makes code much clearer and safer with no overhead whatsoever.

Motti
  • 323
  • 2
  • 8
  • 21
    "C++: The only *seriously* deterministic option. Ask your doctor about it today." – Kyle Strand Feb 10 '14 at 18:29
  • 2
    Follow-up: Rust is now a contender in this field. See [a basic RAII example](https://rustbyexample.com/scope/raii.html) and [documentation about Rust's destructor methods](https://doc.rust-lang.org/book/first-edition/drop.html). – Kyle Strand Oct 10 '17 at 18:34
  • 1
    C will be as deterministic, but requires more work to ensure it actually happens when using malloc-ed memory – Baldrickk Sep 05 '18 at 12:58
  • 1
    @Baldrickk in C you have to write cleanup code everywhere you use a resource. In C++, you write it *once*, in the definition of the resource. Both C and Java suffer from "resource used after disposed" and "leaks resource" bugs, because the cleanup is not *automatic*. Memory is not the only resource. – Caleth Sep 05 '18 at 16:27
71

Is there any satisfiable reason to use C++?

  1. Templates and the STL. You trade a little build time (and some potentially incomprehensible error messages) for a lot of useful abstraction and labor-saving tools, with no appreciable run-time performance hit (although the binary footprint may be a little larger).

    It takes a while to wrap your head around (took me a couple of years before it clicked), but once you do it can make life a lot simpler.

  2. Text processing in C++ is orders of magnitude less painful than it is in C.

John Bode
  • 10,826
  • 1
  • 31
  • 43
  • 3
    STL is the only reason I ever consider using C++. – dan_waterworth Dec 22 '10 at 16:27
  • 36
    +1 for text processing, which I completely forgot about in my answer. – Konrad Rudolph Dec 22 '10 at 17:00
  • I'd like to echo Konrad's sentiment. +1 for strings. – Mr. JavaScript Dec 22 '10 at 18:24
  • 9
    Heh I found especially text processing painful compared to let's say Python.. – Nils Dec 22 '10 at 20:48
  • 7
    Boost is the only reason I still use C++. – Ferruccio Dec 22 '10 at 23:28
  • 34
    @Nils: On a scale of 1 to pain-in-the-ass, text processing in C++ is definitely worse than in more modern languages like Python. It's just that text processing in C *defines* pain-in-the-ass. If the choice is between C and C++ for that particular application, then C++ wins easily. – John Bode Dec 23 '10 at 00:15
  • @dan_waterworth: Agreed. In fact I'll gladly wrap STL for custom containers to prevent C++ leaking into the rest of my source. The string handling in C++ is plain awful. I use C-style strings even in C++. – Matt Joiner Dec 23 '10 at 05:48
  • 1
    Alex Stepanov saved C++ with STL. – ShreevatsaR Dec 23 '10 at 06:07
  • @Matt, that's a trick I like too. – dan_waterworth Dec 23 '10 at 07:39
  • 8
    I dont know why people have such difficulty with things like text processing in C/C++. Just use a library or write your own. Once you've written the low level functions (one-time pain) you gain massive performannce, tight code and greater flexibility. Yes, I'll use Python for quick/dirty command line utilities but for serious production code its C/C++. –  Dec 23 '10 at 10:06
  • 2
    +Tim Ring, some libraries make C++ string processing amazingly easy. After using QString for a while, I'm hard pressed to find Python's advantages in this regard. – MrFox Sep 27 '12 at 17:34
  • yep, std::string, QString, boost string algo and others are cool :3 but i like Ruby – Kokizzu May 13 '13 at 11:32
41

Yes.

If you're looking for executable efficiency, you're down to C or C++, so I'll focus on that.

Even before templates were common, I preferred using C++ over C for the kinds of executables you discuss as early as the mid 1990s for two very simple reasons: object polymorphism and RAII.

I've used polymorphic C++ objects for all kinds of interesting things. For instance, I was working on an embedded Linux system with frame buffer overlays on OMAP and XScale ARM CPUs. The two hardware architectures have different overlay features with very different APIs. I used a common virtual "Overlay" base class to expose an idealized view of overlays, and then wrote "OmapOverlay" and "XScaleOverlay" classes which were instantiated appropriately at runtime, depending on which architecture the code detected it was running on.

To oversimplify, RAII is the idea that you allocate resources connected to an object during the object's constructor, or maybe later on in the object's lifetime, and the resources get deallocated or released in the object's destructor. That's really nice in C++, because objects which are automatic variables are destructed when they go out of scope. For someone who's equally competent in C and C++, it's far easier to avoid resource and memory leaks in C++. You also don't see much C++ code with the very common C meme of a label at the end of a function preceding a bunch of calls to free(), and various goto's in the function block jumping there.

I'm fully aware that you can do all these things with C - it's just a lot more work, way more lines of code, and what you wind up with is a lot uglier and often harder to understand. There's polymorphism code all through the X server internals, and man, is it fugly and weird and frequently hard to trace through.

I also do a lot of work with GNOME technologies like GTK+ and Clutter, all of which are written in C using the GObject system. GObject is like the C++ object system with the nice cover taken off and all the ugly internals exposed, and it usually requires a half-dozen lines of code to do what a one-line C++ method call would do. I'm currently writing some ClutterActors, and while the math is really interesting, I'm constantly thinking, "This would all be so much more succinct and comprehensible in C++".

I also often think, "You know, if I were writing this in C++ instead of C, I'd be out in the living room watching MythBusters with my wife instead of sitting in my office at 9 PM."

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Bob Murphy
  • 16,028
  • 3
  • 51
  • 77
  • 9
    I can really relate to what you're saying here, especially 1) the point about RAII and 2) the thought "You know, if I were writing this in C++ instead of C..." I do a lot of embedded systems development, and even if the team is pretty much a "C" or "C with classes" kind of shop, I really try to encourage RAII for things like interrupt manipulation, mutex operations and tracing/logging (esp. things like toggling I/O lines). And your description of polymorphic frame buffers reminded me of my use of polymorphic message buffers in a distributed system. – Radian Dec 22 '10 at 19:11
29

C++ is about as fast as C (some things are faster, some slower), and it offers better abstractions and organization. Classes work similarly to primitive types, allowing large amounts of code to be used without being held in mind. Operator overloading and templates make it possible to write code that functions better if data representations change. Exceptions can allow easier error-handling. The compiler can be used to check more stuff at compile-time.

The price you pay for this is a fairly nasty learning curve, and it's easier to make subtle mistakes in it than most other languages I'm familiar with.

So, I can't tell whether it would be worthwhile for you to learn it for what you're doing now. You can certainly get by with combinations of Python or Perl and C, but C++ offers both abstraction and performance in one hard-to-get-used-to package.

David Thornley
  • 20,238
  • 2
  • 55
  • 82
  • 15
    There is _no_ case in which C++ is slower than C because you can always use the C way if it is faster (and you care). – Jack Aidley May 15 '13 at 15:44
  • 1
    @JackAidley - Except that C++ does not support restrict and static array parameters. And except that using C++-style in one place forces you to use it at other places. – martinkunev Oct 30 '15 at 19:30
  • @martinkunev `restrict` is used to make exclusions from aliasing optimisations, so how does that help make things _faster_? and what is a "static array parameter"? and how does "style" affect performance? – underscore_d Apr 21 '16 at 13:01
  • 1
    @underscore_d restrict permits optimizations, based on a guarantee for non-aliasing; static array parameters let the compiler assume that a pointer argument is not NULL and that this pointer points to at least a given number of elements; the word "style" has several meanings and putting it out of context changes its meaning - I'm talking about how, for example, exceptions enforce the use of smart pointers. – martinkunev Apr 21 '16 at 16:52
  • @martinkunev My bad, I got `restrict` the wrong way around... guess that was wishful thinking about a `norestrict` keyword ;-) Yeah, C++ lacks that. The static array parameter is news to me; what kind of optimisations does it enable over an array by reference or `std::array` by ref/ptr, or even a ptr/ref + size argument? Can you give an example of a situation in which "exceptions enforce the use of smart pointers" as I've not seen the two together (yet) and am not clear on what you mean. Thanks – underscore_d Apr 21 '16 at 17:08
  • @underscore_d The size of a static array parameter is known at compile time - I wasn't able to find a concrete example of an optimization this enables, but it was added for a reason. Exceptions enforce smart pointers in the sense that throwing an exception will leak memory, unless you use smart pointers or wrap all functions throwing exceptions (which kind of defeats the whole purpose). – martinkunev Apr 22 '16 at 07:39
  • 1
    @martinkunev Hmm, so I wonder whether a static array parameter enables anything functionally different from a C++ template using a `T (&arr)[n]` or `std::array` - will have to research this one more, as there's not a lot of info out there. That makes sense about smart pointers, definitely a good example. If coding on an equal playing field, we wouldn't use exceptions, so none of the potential costs would be incurred... however I suspect you might be alluding to how, once 3rd-party libraries enter the picture, a lot of assumptions are at risk. – underscore_d Apr 22 '16 at 08:17
  • " There is no case in which C++ is slower than C because you can always use the C way if it is faster (and you care).". True but someone one stack overflow will tell you to rather use STL. – Ivor Denham-Dyson Sep 05 '20 at 12:07
20

According to Linus, no :

When I first looked at Git source code two things struck me as odd: 1. Pure C as opposed to C++. No idea why. Please don't talk about portability, it's BS.

YOU are full of bullshit.

C++ is a horrible language. It's made more horrible by the fact that a lot of substandard programmers use it, to the point where it's much much easier to generate total and utter crap with it. Quite frankly, even if the choice of C were to do nothing but keep the C++ programmers out, that in itself would be a huge reason to use C.

In other words: the choice of C is the only sane choice. I know Miles Bader jokingly said "to piss you off", but it's actually true. I've come to the conclusion that any programmer that would prefer the project to be in C++ over C is likely a programmer that I really would prefer to piss off, so that he doesn't come and screw up any project I'm involved with.

C++ leads to really really bad design choices. You invariably start using the "nice" library features of the language like STL and Boost and other total and utter crap, that may "help" you program, but causes:

  • infinite amounts of pain when they don't work (and anybody who tells me that STL and especially Boost are stable and portable is just so full of BS that it's not even funny)

  • inefficient abstracted programming models where two years down the road you notice that some abstraction wasn't very efficient, but now all your code depends on all the nice object models around it, and you cannot fix it without rewriting your app.

In other words, the only way to do good, efficient, and system-level and portable C++ ends up to limit yourself to all the things that are basically available in C. And limiting your project to C means that people don't screw that up, and also means that you get a lot of programmers that do actually understand low-level issues and don't screw things up with any idiotic "object model" crap.

So I'm sorry, but for something like git, where efficiency was a primary objective, the "advantages" of C++ is just a huge mistake. The fact that we also piss off people who cannot see that is just a big additional advantage.

If you want a VCS that is written in C++, go play with Monotone. Really. They use a "real database". They use "nice object-oriented libraries". They use "nice C++ abstractions". And quite frankly, as a result of all these design decisions that sound so appealing to some CS people, the end result is a horrible and unmaintainable mess.

But I'm sure you'd like it more than git.

      Linus
Matthieu
  • 4,559
  • 2
  • 35
  • 37
Jeremy
  • 4,791
  • 1
  • 25
  • 40
  • 64
    I don’t think Linus should be the guy to go to for arguments here. His rants are horribly subjective and immature. He actually does have a few good points but they are so deeply buried (below “bullshit” as well as bullshit) that they are very hard to find. – Konrad Rudolph Dec 22 '10 at 14:55
  • 1
    @Konrad: I know. It was more anecdotal than anything else. – Jeremy Dec 22 '10 at 14:58
  • 19
    Haha, that was a good laugh. I never want to meet this guy. – Felix Dombek Dec 22 '10 at 15:40
  • 30
    Linus reminds me of a very talented roofer who's never hung sheetrock, but calls the sheetrock guys pansies because they use screws instead of nails. – Bob Murphy Dec 22 '10 at 17:09
  • 1
    Linus does kernel development what about other systems? The game industry seems to like C++, I wonder how many C++ features are actually used in games. – Nils Dec 22 '10 at 20:46
  • 8
    Linus has a point but expresses it way too harshly to be taken seriously. –  Dec 22 '10 at 22:27
  • 6
    Linus makes good points here and there, but as others have said, C is not the end all winner. Best tool for the job I always say. With C++ you can end up with some really nasty stuff though. @Nils I used to work for BioWare, and games really push C++ to the edge. Think of a C++ feature, and it's probably used somewhere in there. – Daniel Huckstep Dec 22 '10 at 22:29
  • 2
    @Felix Best comment so far. I guess he named "git" after himself. – ubiyubix Dec 22 '10 at 22:48
  • 39
    I agree with @Daniel, If there is someone that can talk about pushing the boundaries of hardware is John Carmack creator of doom, quake and other games and founder of Id software. He writes this about c and c++ on a twitt a few months ago: "IMO, good C++ code is better than good C code, but bad C++ can be much, much worse than bad C code." http://twitter.com/#!/ID_AA_Carmack/status/26560399301 – Onema Dec 22 '10 at 23:21
  • 4
    I hate this little stinker ;-). – Oliver Weiler Dec 23 '10 at 09:40
  • 7
    I am right up there when it comes to loving Linux, but honestly, I have to disagree on this one. C++ is only as bad as the people who use it. There's nothing inherently wrong with it itself. – Nathan Osman Dec 27 '10 at 05:34
  • 8
    @bromfiets According to himself, *it is*: “I'm an egotistical bastard, and I name all my projects after myself. First Linux, now git.” [Source: git FAQ](https://git.wiki.kernel.org/index.php/GitFaq#Why_the_.27git.27_name.3F) – Konrad Rudolph Jan 20 '11 at 10:30
  • 6
    @Onema "C++ is only as bad as the people who use it." I think that was actually Linus' point. And as far as "pushing the boundaries" go, getting a Unix to run on an i386 seems pretty adventurous. Doom, Quake and Wolfenstien ran *fantastically great* on Linux. Still do. – Dmitri Jun 21 '11 at 15:35
  • 6
    @Jonathan, I would gather that part of being a genius is thinking outside the box, and not caring about what other people think. I suppose that some personalities express that trait by being an asshole. This is pure speculation, of course. – Jeremy Aug 02 '11 at 18:45
  • 4
    The big benefit of C++ is support for large-scale programming. The top Linux guys provide this support by hand and brain and careful organization of their codebase and their development process. They are disciplined, their quality control is merciless, and if you don't like it they don't have to deal with you. So the Torvalds quote makes sense in context -- they're weeding out all the people who think you *can't* do that in C... – comingstorm Sep 28 '12 at 19:50
  • 3
    Can Mr. Linus or some of his followers give some example on how C++ make things horrible? Above @ttsiodras showed in his [answer](http://programmers.stackexchange.com/a/29475/98686) how C can make simple thing horrible but I am yet to see the other way around. – sowrov Aug 04 '13 at 23:52
  • 1
    Am I reading this wrong, or does this basically say, "Quality through un-usability"? Would explain why Linux and git don't seem to have much concern for user experience. – jpmc26 Jan 24 '14 at 01:16
18

I don't think there's any compelling reason to use C++. If you want to do OO programming, you can use Python instead and write the parts that need fast performance in C.

EDIT: There are other languages that interface well with C, so if you don't like Python, there are alternatives.

Larry Coleman
  • 6,101
  • 2
  • 25
  • 34
  • 3
    What about embedded development? Python isn't always available, and the difference in speed between C and well written C++ is negligible on devices past a certain level of processing power. Of course, I suppose a C++ compiler wouldn't always be available either... – James Dec 22 '10 at 14:48
  • @James: I don't do any embedded development, so I can't really speak to that. My answer was in the context of command-line Linux apps. – Larry Coleman Dec 22 '10 at 14:55
  • 6
    @James "well written C++" - there's the catch :( – dss539 Dec 22 '10 at 17:58
  • 5
    I agree with this answer, do the high level with python, since you will write it something like 3 times faster, profile, and then release bottlenecks by replacing them with C/C++. It's redundant to say "replace bottleneck with C++ code" since you won't do any high level with the code you need to be fast, since it will be low level code. There is one thing: i don't know how to interface c++ with python :/. but in term of time spent in front of the screen and efficiency, I think that's the best solution, since most of the C++ code will be fast for nothing ! – jokoon Dec 22 '10 at 22:43
  • You can interface C/C++ with python easily with Cython (http://cython.org/) which allows compiling of "Python" code down to C code, as well as directly declaring C datatypes and calling C functions from python code. – Zhehao Mao Jul 25 '11 at 13:03
  • 8
    Go work for a big financial company and build a complex financial system in a big distributed team in Python and see how you like it. The experience will teach you: a) advantages of type safety, b) advantages of compilers saving your butt, c) LUDICROUS code that Python allows noobs to write. People say that it's easy to shoot your foot with C++ -> some python stuff can work but be borderline insanity. Right now I would so much rather work in C++... – MrFox Sep 27 '12 at 17:49
  • 1
    @suslik: Wow, I'm shocked that anyone would actually use python for that kind of system. I agree with you about bad noob python code; I've seen some myself. – Larry Coleman Sep 28 '12 at 15:53
13

Is there a reason to use C++? Certainly.

Some people might simply prefer using C++ over other options. Asking if there's a reason to use C++ is like asking why we need to have hundreds of flavors of ice cream. Not everyone likes simply sticking with Vanilla.

If developers already are very competent with C++, the question for them may not be 'why use it?', but rather 'why not?'. There seems to be this trendy anti-C++ thing going on in SO right now, but believe it or not, not everyone subscribes to that. Some people may simply like C++ better than the other languages.

Does C++ need to be used for apps? Of course not. But this same exact question can also be asked for any other language. There are very, very few cases where a particular languages needs to be used for an application.

GrandmasterB
  • 37,990
  • 7
  • 78
  • 131
12

I'm just switching from C to C++, and I think the gain is considerable, even if you don't have a need for templates and OOP.

  • Better memory management
  • Stronger type system
  • A better standard library
  • Namespaces
  • etc.
Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
Oliver Weiler
  • 2,448
  • 19
  • 28
7

I'm surprised nobody has mentioned this yet, but C++ introduced us to references, which almost solve all of the problems and pitfalls of pointers:

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

int test = 4;
ModifyVar(test);

Instead of:

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

int test = 4;
ModifyVar(&test);

Much safer and easier too... and without the overhead of passing-by-value.

Nathan Osman
  • 710
  • 6
  • 16
  • 3
    Also much less flexible. References (C++-style) are good at simplifying certain common constructs in a language that also has pointers, but they fall so far short of being a replacement for pointers, it isn't even funny. And your example is not-at-all a good case for references. – Ben Voigt Dec 25 '10 at 23:11
  • 3
    @Ben: Then can you please explain *why* it's a bad example? – Nathan Osman Dec 26 '10 at 01:45
  • 6
    @George: Because nothing changed, except it's two (count 'em) characters shorter? It's not solving any problems, it's not highlighting any pitfalls, it doesn't even do anything cool like extend the lifetime of a temporary variable (which references are good at). – Ben Voigt Dec 26 '10 at 02:16
  • @Ben: You're forgetting something - the reference is always valid. Pointers can point to anything (including NULL) which can lead to all kinds of memory errors if things aren't done right. References can never be NULL and the address that they point to can never be changed. – Nathan Osman Dec 27 '10 at 00:19
  • 5
    @George: "the reference is always valid" is flat out false. I'll give an example if you need one, but I'm hoping that you're expert enough to already be aware of this. And I'm not talking about forming an invalid reference using an invalid pointer, either. Functions that use pointers need documentation stating the preconditions on the arguments. But practically speaking, all functions need that level of documentation, so it's absurd to call that a strike against pointers. – Ben Voigt Dec 27 '10 at 00:47
  • @Ben: When I say the reference is always valid, I don't mean that it always points to valid memory - I meant that there's no such thing as a NULL reference. – Nathan Osman Dec 27 '10 at 00:51
  • @NathanOsman - The C++ standards is the only place where NULL references don't exist. – martinkunev Oct 30 '15 at 19:43
  • This answer just substitutes a few characters and then asserts this proves the superiority of references, with no information on what "the problems and pitfalls of pointers" were or why references solve them. – underscore_d Feb 12 '16 at 10:02
5

The where and why are usually going to be:

  • familiarity
  • desired language features
  • specific libraries you want to use
  • performance requirements

For server side programming you can often choose from a myriad of different languages, compiled or interpreted. Usually the choice of language is driven by which platform you or your team will be most effective on. Or if you don't yet have a team, the availability of skills in the market.

On a side note I don't really understand deciding to use C/C++ based on performance (only) since many scripting languages are extensible with C/C++. You get the benefit of a rapid development language coupled with the ability to migrate the slow portions into C/C++ extensions. Certainly if your doing systems programming where every op counts it's understandable, but in most app development I don't get it.

dietbuddha
  • 8,677
  • 24
  • 36
4

C++ vs Python vs Perl can't be judged easily. It depends on the project and requirements.

C++ has an arsenal of utilities from long ago, running in many platforms. But it is painful to start walking through streams for just passing String to Integer and reverse.

C++ on the other hand, has an awful deal with dependencies on libraries. Once you compile something in GCC X or VC++ Y, then you can't rely that the code will run by the next version of those tools. The same hell is on Windows, the same hell is on Unix too.

Perl, takes its power from Unix world but especially as a regular expression tool. This is what it is used most of the time. Along with some pretty serious tools that even Java can't do it in a normal way (check out how to upload a file to a web server), Perl is "just do it".

Python is easy, flexible and a dynamic language. So easy that you can send an integer to a function, the script expects string, yet you can have a result! Unexpected though, but a result. So it the programmer needs to be very cautious. IDLE offers some debugging, but when you have TELNET'ed to a system, or SSH'ed in three levels down and you want to find your problem, the debugger won't be there to stand next to you. But, it can do some great math work fast.

Java is an ecosystem of buzzwords, alien technologies, and big words and when you want to just upload a file to webserver, you find that you can do it only if the server has JSP. If you want to call system libraries or system functions like monitoring you find that you have to dig out a lot. And perhaps to reach JNI and OK...you think then..."Why, Lord?"

Apart from that, Java is a great tool for business suites, and multithreading, I liked it a lot.

Fast to make a program and show to your CV "Oh, I know that technology too" and your want-to-be boss, be amazed! Even though, the technology might not be that needed... (OK, folks, I hate the Spring Framework....)

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
hephestos
  • 103
  • 4
  • 1
    alas, you have to consider that Python has version dependencies - especially once you migrate to Python 3, same with perl.. or has anyone bothered to move to Perl 6 yet? Everything has nasty dependencies :( – gbjbaanb Oct 05 '12 at 13:11
3

Linux? What about "object oriented Pascal" or "D"?

Suggestions:

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
3

The thing to keep in mind while choosing a language, is what benefit you will get from using it, and how long it will take to get it.

The main idea between languages like python and perl is to do more with less man time, but with more cpu time. In fact you will spend more time coding a python or perl script than it will be executed, but you get my point.

The advantage of C/C++ is that they are fast, but at a cost of syntax and strong typing: you have to do a lot of thing yourself so that the computer has not to choose it at compile time.

When you make a code, some lines will be ran a lot more than others, and those lines are the one that pose a problem. On the other hand, all the rest of the code, the one you spent a lot of time on, is executed much much less often. You might have heard it, but it is the infamous 80/20 rule, and you won't be able to bypass such rule.

The solution to this problem, is to use an easier language (by easier I mean more developer friendly: less typing, lazy interpretation, a lot of preexisting routines and stuff, etc.) to do all your code.

You will do it so quickly compared to if you would have done it with C or C++, it would have taken much more brain ache.

Your program will be slow, but with a profiler, you isolate the part which are ran 80% of the time, and you do them with C or C++.

By prorgamming this way, you saved a lot of time, and your program is as efficient, as much fast, has much less chances to leak memory, and you saved time.

Scripting languages were designed to be on the side of the developer, but optimisation is still possible. Of course you can be a design pattern magician or a STL voodoo or even a lisp warrior, and maybe an haskell monk. But languages makes us talk to computers, languages are not made for us to BE computers !

jokoon
  • 2,262
  • 3
  • 19
  • 27
2

The C++ I use is called C with classes!

0

No, not at all. If you don't need the performance and there is a library you can use the other language then don't bother with C/C++. I only do it nowadays when I target embedded systems that can't (easily?) run languages. Sometimes I use C because I am writing a plugin but really no.

However, I wouldn't use Python, Perl, etc. to avoid using C. My preference is actually C#, because I like a good library (which is a strength of .NET), and I like statically typed languages. Boo is a good alternative. But really Haskell, OCaml, D, ML and such are all fine.

Peter Mortensen
  • 1,050
  • 2
  • 12
  • 14
  • 7
    You missed the point. – Matt Joiner Dec 23 '10 at 06:16
  • @Matt Joiner: I'm sure i haven't. What did i miss? –  Dec 23 '10 at 06:51
  • The question is about not using C++. – Matt Joiner Dec 23 '10 at 08:08
  • @Matt Joiner: hmm, on another look i can see that being asked. But it seems like i answered that too (i said dont bother and the alternatives i use) –  Dec 23 '10 at 09:03
  • I almost want to downvote this because of C#... – Vreality Jan 14 '14 at 09:42
  • @Vreality: What's wrong with C#? Do you prefer Java? –  Jan 15 '14 at 15:25
  • @acidzombie24 Far from it -- I prefer almost anything but the two (C or C++ are much better IMO), but I suppose it's only opinion. – Vreality Jan 16 '14 at 13:48
  • @Vreality: Really? Now I really want to know. What's wrong with them? I dislike java but C# is a statically typed language with decent syntax, has generics, ditches multiple inheritances for interfaces and trades power/speed for safety/exceptions. I can't see why you'd like C/C++ much better unless you think all languages are bad except C/C++ and maybe D+Haskell –  Jan 16 '14 at 14:33
  • @acidzombie24 C# is Microsoft oriented and not well supported on Linux. Moreover, it's slower and less powerful. Essentially, what you see as benefits, I see as detriments. Also, Microsoft and safety aren't too be associated with one another in my opinion. – Vreality Jan 19 '14 at 20:11
  • @acidzombie24 However, I agree about Haskell. It's a safe language that's fast yet still can be very powerful (especially through monads). – Vreality Jan 19 '14 at 20:43
  • Mono has excellent support on linux and runs incredibly well. My servers use it. Anything not C/C++ is slower and less powerful. –  Jan 20 '14 at 00:54
  • @acidzombie24 Yes, mono is nice, but it's just not the same. Besides, I was more concerned with performance. There are languages faster than C/C++ -- assembly being one of them. :p Here's an article that voices a few of my objections: http://www.linuxuser.co.uk/features/mono-a-gratuitous-risk-the-free-software-column – Vreality Jan 26 '14 at 18:43
0

There's actually a single answer to all questions formed like this. The best reason to use tech X instead of tech Y (where X and Y are roughly on the same level [like just about all contemporary programming languages are]) is because you already know X and don't know Y.

(but after Haskell arrived, there has been no reason to use anything else)

vegai
  • 693
  • 3
  • 8