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

From Pin Eight
Jump to: navigation, search
m (Minuses: In case someone doesn't have a copy of EC++ 2e around)
(Minuses: Merged from http://www.pineight.com/rant/#cbloatbloat per front page notice)
Line 21: Line 21:
 
== Minuses ==
 
== Minuses ==
 
C++ also has some features requiring possibly expensive runtime library support:
 
C++ also has some features requiring possibly expensive runtime library support:
* <code>throw</code>
+
* <code>[[wikipedia:Exception handling|throw]]</code>
 
* the default version of <code>new</code> without <code>std::nothrow</code>, which throws <code>std::bad_alloc</code>
 
* the default version of <code>new</code> without <code>std::nothrow</code>, which throws <code>std::bad_alloc</code>
* <code><nowiki><iostream></nowiki></code>
+
* <code><[[wikipedia:iostream|iostream]]></code>
  
 +
=== Templates ===
 
Templates have a couple drawbacks:
 
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 <code>typedef</code>. For example, an error message involving the <code>std::string</code> type is likely to provoke this reaction: "[http://www.sgi.com/tech/stl/basic_string.html <code>basic_string</code>]? I'm using C++, not [[wikipedia:BASIC|BASIC]]! And what the fsck is [http://www.cplusplus.com/reference/string/char_traits/ <code>char_traits</code>]?" (True, implementations are not the language, but a language is only as good as its best [[wikipedia:free software|free]] implementation.)
 
* 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 <code>typedef</code>. For example, an error message involving the <code>std::string</code> type is likely to provoke this reaction: "[http://www.sgi.com/tech/stl/basic_string.html <code>basic_string</code>]? I'm using C++, not [[wikipedia:BASIC|BASIC]]! And what the fsck is [http://www.cplusplus.com/reference/string/char_traits/ <code>char_traits</code>]?" (True, implementations are not the language, but a language is only as good as its best [[wikipedia:free software|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 <code>extern template</code> allowing for [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm explicit instantiation], but it's not in C++98, and [http://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport not all compilers support it].
 
* 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 <code>extern template</code> allowing for [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2006/n1987.htm explicit instantiation], but it's not in C++98, and [http://wiki.apache.org/stdcxx/C%2B%2B0xCompilerSupport not all compilers support it].
  
 +
=== Exceptions ===
 
Exceptions (<code>throw</code>) also have a couple drawbacks:
 
Exceptions (<code>throw</code>) also have a couple drawbacks:
 
* Though exceptions have little to no runtime speed penalty in a modern C++ compiler, the size of the required library support might cause a problem on embedded or handheld devices with less than about a megabyte of RAM.
 
* Though exceptions have little to no runtime speed penalty in a modern C++ compiler, the size of the required library support might cause a problem on embedded or handheld devices with less than about a megabyte of RAM.
Line 38: Line 40:
 
[[wikipedia:Electronic Arts|EA Games]] created an [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#Appendix_18 out-of-memory-aware allocator].
 
[[wikipedia:Electronic Arts|EA Games]] created an [http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2271.html#Appendix_18 out-of-memory-aware allocator].
  
 +
=== iostream ===
 
The <code><nowiki><iostream></nowiki></code> library is another divisive issue.
 
The <code><nowiki><iostream></nowiki></code> library is another divisive issue.
It was envisioned as a type-safe alternative to <code><nowiki><cstdio></nowiki></code>, but implementations are [http://yosefk.com/c++fqa/io.html hairy], [http://www.pineight.com/rant/#cbloatbloat bloated], [http://www.vterrain.org/Implementation/effective.html inefficient].
+
It was envisioned as a type-safe alternative to <code><nowiki><cstdio></nowiki></code>, but implementations are [http://yosefk.com/c++fqa/io.html hairy], bloated, and [http://www.vterrain.org/Implementation/effective.html inefficient].
 +
[[wikipedia:Hello World program|Hello World programs]] with <code>-Os</code> and statically linked libstdc++ in one version of MinGW resulted in 5,632 bytes for <code><nowiki><cstdio></nowiki></code> but 266,240 bytes for <code><nowiki><iostream></nowiki></code>.
 +
A [http://www.devkitpro.org/ devkitARM] project targeting Game Boy Advance had similar results: 5,156 bytes for C-style I/O and 253,652 bytes for <code><nowiki><iostream></nowiki></code>; even removing some unreachable code with <code>-Wl,-gc-sections</code> couldn't get it 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.
 +
Some third-party C++ standard library implementations such as [http://cxx.uclibc.org/ uClibc++] are designed for space efficiency and leave out features such as locale support that aren't as useful in small-memory systems.
 +
 
 
Yet some C++ fanboys claim that anything using good old <code><nowiki><cstring></nowiki></code> and <code><nowiki><cstdio></nowiki></code> instead of new-fangled <code><nowiki><string></nowiki></code> and <code><nowiki><iostream></nowiki></code> isn't in the spirit of C++, [[wikipedia:no true Scotsman|whatever that means]]. They cling to item 2 in the second edition of Scott Meyers' ''Effective C++'', which promotes <code><nowiki><iostream></nowiki></code> over <code><nowiki><cstdio></nowiki></code>, and ignore item 23 of his sequel ("consider alternative libraries"). It appears that Meyers eventually recognized that <code><nowiki><iostream></nowiki></code> is imperfect and removed item 2 from the third edition.
 
Yet some C++ fanboys claim that anything using good old <code><nowiki><cstring></nowiki></code> and <code><nowiki><cstdio></nowiki></code> instead of new-fangled <code><nowiki><string></nowiki></code> and <code><nowiki><iostream></nowiki></code> isn't in the spirit of C++, [[wikipedia:no true Scotsman|whatever that means]]. They cling to item 2 in the second edition of Scott Meyers' ''Effective C++'', which promotes <code><nowiki><iostream></nowiki></code> over <code><nowiki><cstdio></nowiki></code>, and ignore item 23 of his sequel ("consider alternative libraries"). It appears that Meyers eventually recognized that <code><nowiki><iostream></nowiki></code> is imperfect and removed item 2 from the third edition.
  
 
== External links ==
 
== External links ==
 
*[http://yosefk.com/c++fqa/ C++ FQA Lite], offering a rebuttal to the fandom's C++ FAQ Lite
 
*[http://yosefk.com/c++fqa/ C++ FQA Lite], offering a rebuttal to the fandom's C++ FAQ Lite

Revision as of 03:06, 23 September 2010

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 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:

  • Though exceptions have little to no runtime speed penalty in a modern C++ compiler, 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.

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.[1] 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. 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>; even removing some unreachable code with -Wl,-gc-sections couldn't get it 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. 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.

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.

External links

  • C++ FQA Lite, offering a rebuttal to the fandom's C++ FAQ Lite