Difference between revisions of "C++ vs. C"

From Pin Eight
Jump to: navigation, search
(iostream: idiomatic vs. idiotic)
(Google is not a fan of C++ exceptions)
Line 35: Line 35:
 
* Even if you have determined that a particular compiler imposes little to no runtime speed penalty for exceptions, the size of the required library support might cause a problem on embedded or handheld devices with less than about a megabyte of RAM.
 
* Even if you have determined that a particular compiler imposes little to no runtime speed penalty for exceptions, the size of the required library support might cause a problem on embedded or handheld devices with less than about a megabyte of RAM.
 
* C++98 has no counterpart to the <code>finally</code> keyword of Java and Python. True, there isn't as much need for <code>finally</code> in C++ as in languages that rely on a garbage collector, given the [[wikipedia:Resource Acquisition Is Initialization|idiom of allocating resources in constructors]] that C++'s deterministic destruction allows. But a method often still needs to restore the object's fields to a consistent state before eating or rethrowing the exception. C++0x addresses this by letting the programmer build a scope-guard with <code>std::shared_ptr</code> and lambda expressions.
 
* C++98 has no counterpart to the <code>finally</code> keyword of Java and Python. True, there isn't as much need for <code>finally</code> in C++ as in languages that rely on a garbage collector, given the [[wikipedia:Resource Acquisition Is Initialization|idiom of allocating resources in constructors]] that C++'s deterministic destruction allows. But a method often still needs to restore the object's fields to a consistent state before eating or rethrowing the exception. C++0x addresses this by letting the programmer build a scope-guard with <code>std::shared_ptr</code> and lambda expressions.
 +
* If a function throws exceptions, all callers have to be aware of all exception types that it may throw, and all callers have to be written in C++ using exception style so that they can catch the exceptions. This is one reason why Google is not a fan of C++ exceptions.<ref> Andrew Binstock. "[http://www.drdobbs.com/architecture-and-design/the-scourge-of-error-handling/240143878 The Scourge of Error Handling]". ''Dr. Dobb's'', 2012-12-05. Accessed 2012-12-08.</ref>
  
 
On platforms without virtual memory, a program must be aware of possible out-of-memory conditions.
 
On platforms without virtual memory, a program must be aware of possible out-of-memory conditions.
Line 59: Line 60:
  
 
"As an embedded programmer, I shun C++." -- Arlet, [http://slashdot.org/comments.pl?sid=2503778&cid=37910334 2011-11-01]
 
"As an embedded programmer, I shun C++." -- Arlet, [http://slashdot.org/comments.pl?sid=2503778&cid=37910334 2011-11-01]
 +
 +
== References ==
 +
<references />
  
 
== External links ==
 
== External links ==
 
*[http://yosefk.com/c++fqa/ C++ FQA Lite by Yossi Kreinin], offering a rebuttal to the fandom's C++ FAQ Lite
 
*[http://yosefk.com/c++fqa/ C++ FQA Lite by Yossi Kreinin], offering a rebuttal to the fandom's C++ FAQ Lite
 
*[http://stackoverflow.com/questions/3171647/errors-in-c-fqa A rebuttal to the rebuttal], which admits that [http://slashdot.org/comments.pl?sid=2574298&cid=38376714 Yossi makes a few good points]
 
*[http://stackoverflow.com/questions/3171647/errors-in-c-fqa A rebuttal to the rebuttal], which admits that [http://slashdot.org/comments.pl?sid=2574298&cid=38376714 Yossi makes a few good points]

Revision as of 22:50, 8 December 2012

This is a mini-rant, a short essay refuting a common misconception among users of an Internet forum. If you think this essay is FUD, feel free to explain why on the essay's talk page.

The C++ programming language brings improvements over its predecessor C, but fans of other languages point out that C++ is still not perfect. Over a decade after the 1998 standardization of the C++ programming language, the C++ vs. C debate continues.

Pluses

Compared to C, C++ has a bunch of new language features with little or no runtime overhead because they are translated to code equally as efficient as the equivalent C code:

  • namespaces
  • function overloading
  • type-safe new(std::nothrow)
  • STL, the part of the C++ standard library with containers and algorithms
  • non-virtual methods
  • references, needed by operator overloading

A few features are as efficient as C yet still rawther deceptive and easy to misuse because the "simple" syntax hides how much code is actually being generated:

  • operator overloading, when compared to ordinary function-call syntax
  • virtual (polymorphic) methods, when compared to C function pointer tables, especially the pure virtual method's undefined behavior that some compilers may implement as an exception
  • templates instantiated several times, when compared to using the preprocessor to instantiate multiple copies

PROTIP: A class is a struct whose first member is private. That's the only difference.

Minuses

C++ also has some features requiring possibly expensive runtime library support:

  • throw
  • the default version of new without std::nothrow, which throws std::bad_alloc
  • <iostream>

Templates

Templates have a couple drawbacks:

  • Type names in error message become far more difficult to interpret. Common implementations may expand a template type name fully in diagnostic messages even if the source code accesses the type through a typedef. For example, an error message involving the std::string type is likely to provoke this reaction: "basic_string? I'm using C++, not BASIC! And what the fsck is char_traits?" (True, implementations are not the language, but a language is only as good as its best free implementation.)
  • Programmers can lose track of for how many different type combinations they have instantiated a template, causing code size to balloon. There is a common extension called extern template allowing for explicit instantiation, but it's not in C++98, and not all compilers support it.

Exceptions

Exceptions (throw) also have a couple drawbacks:

  • Some platforms require different stack frame formats for code that uses exceptions and code that does not use exceptions. Unless you completely disable exception support using compiler flags, the exception support may still eat up a few percent of CPU time, roughly 8 to 10 percent in GCC.[1]
  • Even if you have determined that a particular compiler imposes little to no runtime speed penalty for exceptions, the size of the required library support might cause a problem on embedded or handheld devices with less than about a megabyte of RAM.
  • C++98 has no counterpart to the finally keyword of Java and Python. True, there isn't as much need for finally in C++ as in languages that rely on a garbage collector, given the idiom of allocating resources in constructors that C++'s deterministic destruction allows. But a method often still needs to restore the object's fields to a consistent state before eating or rethrowing the exception. C++0x addresses this by letting the programmer build a scope-guard with std::shared_ptr and lambda expressions.
  • If a function throws exceptions, all callers have to be aware of all exception types that it may throw, and all callers have to be written in C++ using exception style so that they can catch the exceptions. This is one reason why Google is not a fan of C++ exceptions.[1]

On platforms without virtual memory, a program must be aware of possible out-of-memory conditions. The STL allows passing an allocator to all containers, but most implementations appear to exhibit undefined behavior when allocate() returns 0 like new(std::nothrow) does. I've been told one STL implementation can be built with nothrow in mind: STLPort.[2][3] EA Games created an out-of-memory-aware allocator.

iostream

The <iostream> library is another divisive issue. It was envisioned as a type-safe alternative to <cstdio>, but implementations are hairy, bloated, and inefficient. This goes double if you have to use a statically linked implementation of the C++ standard library, either because the operating system provides no C++ standard library (e.g. handheld video game systems) or because your compiler's C++ ABI differs from that of the operating system publisher's own development tools (e.g. MinGW). Hello World programs with -Os and statically linked libstdc++ in one version of MinGW resulted in 5,632 bytes for <cstdio> but 266,240 bytes for <iostream>. A devkitARM project targeting Game Boy Advance had similar results: 5,156 bytes for C-style I/O and 253,652 bytes for <iostream>. (This is expected; Thumb and x86 have comparable code density.) Even removing some unreachable code with -Wl,-gc-sections couldn't get the GBA project below 180,032 bytes. (For comparison, the GBA's main RAM is 262,144 bytes.) These tests are with GNU libstdc++, which initializes date, time, and money aspects of a locale for each stream even if the program never shifts a date, time, or money object into the stream. This is because it was conceived before templates and instead uses virtual inheritance and "facets", which C++ implementations can't optimize well.[4] Some third-party C++ standard library implementations such as uClibc++ are designed for space efficiency and leave out features such as locale support that aren't as useful in small-memory systems. In fact, one C++ advocate claims that comparing memory usage of C++ to C by targeting a sub-megabyte platform with GNU libstdc++ sets up a huge straw man.[5]

Yet some C++ fanboys claim that anything using good old <cstring> and <cstdio> instead of new-fangled <string> and <iostream> isn't in the spirit of C++, whatever that means. They cling to item 2 in the second edition of Scott Meyers' Effective C++, which promotes <iostream> over <cstdio>, and ignore item 23 of his sequel ("consider alternative libraries"). It appears that Meyers eventually recognized that <iostream> is imperfect and removed item 2 from the third edition. Someone who knows a few people on the standards committee thinks Boost.Format is idiomatic and <iostream> is just idiotic.

"As an embedded programmer, I shun C++." -- Arlet, 2011-11-01

References

  1. Andrew Binstock. "The Scourge of Error Handling". Dr. Dobb's, 2012-12-05. Accessed 2012-12-08.

External links