I'm starting to write an article on what I'm calling "C++ Urban Myths" - that is, ideas and conceptions about C++ that are common but have no actual roots in reality. Some that I've come up with so far are:
TR1 is part of standard C++
It is faster to use iterators to access a vector than operator[]
The C++ Standard contains something called the STL
I'm wondering if the SO C++ community can come up with any better ones? Ideally, they should be expressible in a single sentence, and not involve any code.
Edit: I guess I didn't make it clear enough that I was interested in myths believed by C++ developers, not misconceptions held by non-C++users. Oh well...
There is a language called C/C++.
There is common misconception that if you know C++ you can easily write C code and if you know C that you can easily start writing C++ code.
These languages are so different that I would never put them one near other.
cout << endl;
is the same as cout << "\n";
They are absolutely not! cout << "\n";
simply adds a character to the output stream. cout << endl;
does the same but also flushes the stream, which implies a system call, which is terribly slow.
This is IMHO one of the root cause of the C++ iostream reputation to be slow.
cout << "\n"
, behind the scenes, it will write "\r\n" to the actual file if the platform needs it. This translation is never done if you specify the ios_base::binary
flag when opening the file. - Didier Trosset
cout << "\n";
simply adds a character to the output stream". That's not true. It may also flush the stream, where adding any other character would not, because cout
is often line-buffered. It's just not required to flush as endl
is. - Steve Jessop
iostream
is also slow because of unavoidable failure checks, locales, and the lack of a guarantee that you can expand the buffer size. Learning it is also harder in my experience than reimplementing my own buffer. - Potatoswatter
stream.put(stream.widen('\n')); stream.flush();
(C++03, 27.6.2.7/1). The use of widen handles non-char streams. - community_owned
'\n'
to /dev/null
takes 0.57 seconds; printing 10 million times std::endl
to /dev/null
takes 1.48 seconds. - Thomas
cout << '\n'
will be probably be faster than cout << "\n"
:-) - Matt Curtis
C++ is slower than C.
std::string::length
is a lot faster than strlen
... - FredOverflow
restrict
in the C code. And so on. - Steve Jessop
restrict
as an extension also in C++. Not only on pointers, also on references! - slacker
std::sort
will outperform qsort
, almost always. Simply because function pointers cannot be inlined in either C or C++, but std::sort allows you to pass a functor, which can be inlined. A counterpoint to this is that if you pass the same function pointer to both, they'll likely execute in the same time. However, C++ provides a facility that is faster. - Nathan Ernst
The STL is slow is a myth. It is often faster than writing your own containers (except for highly specialist uses like EASTL, but you certainly need an uncommon level of expertise to beat the STL), and modern compilers optimise it quite well. Occasionally you can still find fixed C arrays or containers reinvented "for efficiency," when such code may well be slower (not to mention more error-prone than the STL).
Old one, but still strong:
You need to learn C first.
s != "hello"
does not work... missing templates; if you need "vectors", "dictionary"... you can't use STL and have to figure out which library is "popular", or "efficient enough", or whatever...) - ShinTakezou
You have to manage the memory manually
Ok, it's a bit tricky (and somewhat provocative point of view), but using RAII you can cover almost every situation. For some extreme cases, smart pointers do the work.
You have to choose a "safe subset" of C++. Don't use exceptions or templates or multiple inheritance or operator overloading or collections or smart pointers or function objects or custom memory allocators, because those features are far too complicated for mere mortals to understand and use correctly.
Truth: The "complicated" parts of C++ are there because they can make programs simpler. Don't prohibit their use because you are not familiar with them or because you've seen them misused.
If you use new[]
, then delete
(not delete[]
) on the obtained pointer you have a memory leak.
Actually you have undefined behavior. Depending on circumstances either it just plain works or you have a heap corruption, or some other damage much worse than a memory leak, but almost never a memory leak [1].
[1] http://stackoverflow.com/questions/1913343/how-could-pairing-new-with-delete-possibly-lead-to-memory-leak-onlyIf you make a mistake, you blow off your leg.
Most people will die when that happens, and there are far more C++ programmers than can be accounted for taking this into consideration.
0) In C++, you must mess around with pointers, that's old and dangerous, use C#
Gee, #include <boost/shared_ptr>
or one of the like. Actually, it is often easier to produce mess in your sowonderful C#:
static void Main () {
foo();
bar();
}
static void foo () {
var f = new StreamWriter ("hello.txt");
f.Write ("hello world");
}
static void bar () {
var f = new StreamReader ("hello.txt");
Console.WriteLine (f.ReadToEnd ());
}
"Unhandled IOException: The process cannot access the file 'hello.txt' because it is being used by another process."
Those claims, btw, are often made by those who happen to never have heard of RAII, and about how far you can get without even smart-pointers.
1) #define SAFE_RELEASE(x) ...
without words
2) Heap-Allocation in C++ is sooo slow when compared to .net
Well, uhm, in C++, we use the stack most of the time, thanks.
3) foo=new Foo(); if (foo==NULL) {...}
See 1).
(the following are more compiler related, not sure if they really fit the topic)
Appendix A.0) Porting from MSVC to g++: found g++ bug!!!!
Answer: You must add typename
there.
using
' statement. - George Stocker
new
a stream, RAII comes usually to the rescue. Admittedly, there's a bunch of other pitfalls, but C++ is often frowned more upon than deserved :) - phresnel
int main(){std::ofstream o("hello.txt"); if(o){o<<"hello";}}
. Personally I fail more often in C# than in C++ (e.g. because of missing const correctness or missing builtin copy semantics for clas types), but that surely differs by what one does in that language. Did not want to start a flame here :D - phresnel
C++ is less portable than Java.
The opposite is true.
MenuBar
. In the case of JMenuBar
s it make a value-equivalent MenuBar
and docks that. Further changes to the JMenuBar (recent docs, "Windows" menu option) do not effect the application menu bar. Plus there is the whole DISPOSE_ON_CLOSE win/unix behavior vs the HIDE_ON_CLOSE OSX behavior. See: java.sun.com/developer/technicalArticles/JavaLP/JavaToMac for more. - KitsuneYMG
The Standard allows NULL
to be something other than zero, so you should not use 0
.
Urban Myth!
NULL
s with nullptr
s when thy finally come to us than it is with 0
s. - Dmitry
0L
when initialising a long, either, or 0.0
when initialising a double, or '\0'
for a char. @litb: it's not a myth that you should use NULL, but it is a myth (if it's believed at all) that the reason given is an argument for using NULL. - Steve Jessop
(void)*0
. - GMan
0
in a pointer context will generate a null pointer. In C++, the macro NULL
should expand to 0, not ((void*)0)
(which was common in some C implementations). The internal representation of a null pointer may be something other than all zero bits. On some exotic platforms, null pointers are some special address other than 0. C++0x is adding they keyword null_ptr
because using a literal 0 can be ambiguous in certain contexts (e.g., templates). I assume we'll start defining NULL
to be null_ptr
then. - Adrian McCarthy
NULL
to nullptr
, because while NULL
must be an integer (and so is convertible to int
or actually is an int
, for instance), nullptr
is not convertible to int
. In general, i avoid saying "in a pointer context". I just say "will be converted to a null pointer when needed". Because the next question will be, what is a "pointer context"? - Johannes Schaub - litb
NULL
is useful in gcc in that they don't use 0 (as the standard says). It uses __null
which is a fancy compiler specific 0 that emits a warning when NULL is use in an integer context instead of a pointer. __null
is halfway between 0 and nullptr
. - deft_code
0
(that's another myth). Instead, it requires them to use something that evaluates to zero. __null
is such an expression that evaluates to zero. - Johannes Schaub - litb
C++ is inefficient for embedded development
C++ is only C with Classes (see STL...)
std::string
class does non-threadsafe things in what looks like threadsafe code. - Mike DeSimone
C is a subset of C++. Every valid C program is also a valid C++ program.
Truth: C is not a subset of C++. Not every valid C program is also a valid C++ program.
struct
initialization stuff with struct
s that do not have methods. Having to leave out so much of C because you want to write a header that works in both languages is a pain. - Mike DeSimone
Calling virtual functions is extremely slow
I've heard it many times, including here, on StackOverflow. Modern virtual tables implementations dispatch virtual function calls quite fast, with small and predicatable overhead, compared to calling usual functions. In the simplest single-inheritance case it requires just an additional access to one memory cell. I started my blog with an "article" about it [1].
[1] http://coldattic.info/shvedsky/pro/blogs/a-foo-walks-into-a-bar/posts/3FQA Lite is an aggregation of bad-faith-formulated self-contradicting criticism of C++ written by someone with too much time on his/her hands using it to practice biased argumentations and written diarrhea.
My prefered quote: http://yosefk.com/c++fqa/exceptions.html#fqa-17.4
WARNING - cyclic dependency between C++ features detected! You see, exceptions are a must in this language so that you can handle errors in all the functions which fail to look like functions, such as constructors & operators. Then it turns out that you need constructors to work with exceptions - unless each and every piece of memory you acquire is not immediately assigned to some smart pointer, your code is not exception safe. This is known as "Resource Allocation Is Initialization" (RAII) in the C++ community; it's supposed to be a good thing.
Disclaimer: Note that FQA Lite can still be useful when one needs to know the little known corners of C++... Just ignore the gratuitous bashing
[1] http://yosefk.com/c++fqa/How are you going to figure out whether your program manages resources correctly or not when it's littered with smart pointers of different kinds, especially in case there's any non-trivial scenario there, like the cases when "ownership" (the right & duty to dispose a resource) is passed from object to object
... by umm, thinking? - Skurmedel
If your application is not CPU bound, you aren't getting any benefits from using an unsafe language like C++ except for extra quality time with the debugger
- BlueRaja - Danny Pflughoeft
There are developers who understand C++
Modern C++ style is MFC style
Macros are easier to use than templates
Exceptions are a really bad idea, slow and complicated to understand and maintain
Exceptions are a really good idea, clean and elegant an make code easier to read
EDIT: I have heard both passionately expressed. Since both cannot be true and each camp is full of smart people who care then they both must be myths
For the record I fall into the pro-exception camp.
goto
is IMHO better than an exception directly to an enclosing scope. Exceptions have a time and a place, but pretty they are not. - Potatoswatter
StopIteration
, but it's not recommended in C++. - Mike DeSimone
try { /* code goes here */ } catch(...) {}
. It's opt-out, to be sure, but it's also pretty ignorant. - Mike DeSimone
C++/CLI is C++.
Truth: C++/CLI and C++ are different languages.
It's not the language that's horrible, its the programmers who use it in a naive way. And just as there are bad C++ programmers, you can hardly swing a dead cat without hitting bad programmers in [insert favorite language here].
C++ is a multi-paradigm language. It's not object-oriented in the sense that "everything is an object" the way it is in Ruby or .NET languages. C++ supports object-oriented programming, but it also supports generic programming, functional programming, and just about any other programming paradigm you can imagine.
According to A. Stepanov [2], no, it's not.
[1] http://article.gmane.org/gmane.comp.version-control.git/57918"It's more straightforward to use char* than std::string."
char*
is also necessary for inter-operation with C libraries, or pre-STL C++ code. - dan04
c_str
method on a std::string
; - Atmocreations
Arrays and pointers are the same thing (ok really more a C myth)
There is such language Unmanaged C++.
This drives me crazy! There is no such thing unmanaged-C++. There is C++ and some other languages called C++/CLI. C++ is not managed.
C++ is not a modern language. It is superseded by Java and C#. This one is totally wrong and makes me laugh every time I hear it. Many of my IT friends believe it. Actually, C++ provides more abstraction mechanisms than Java or C#. There is a spin off to this myth.
Newer versions of Visual Studio don't support C++. I heard it from IT folks as well. Some of them believe that Microsoft stopped upgrading its C++ compiler sometime after the introduction of C#.
It is very hard to write exception safe code in C++ compared to Java because of memory leaks. Wrong again. Memory leaks are only a small part of exception safety. There is more to exception safety than memory leaks. Garbage collection helps with memory leaks only.
It is hard to write multithreaded code in C++ compared to Java and C# Wrong. Multithreading is hard in Java and C# as well. Multithreading is a complex and completely different programming paradigm. Once you mastered the art of parallelization, you can use C++, Java or C# to do multithreading.
Java isn't slower than C++ This isn't true. Face it, C++ allows to do more low optimizations, because it is a native language. Competent hackers can cook up highly optimized C++ code which can't be matched in Java no matter how hard you try. But it is true, that incompetent C++ programmers can screw things up easily.
Myth: It is possible to use the STL correctly while in exception denial.
A few STL methods throw exceptions (e.g., std::vector::at). More importantly, the container classes expect the allocator to throw std::bad_alloc when an allocation cannot be satisfied.
If your local coding standard enforces exception denial and thus you disable exceptions in the compiler, these errors crash or corrupt data in STL calls, beyond the ability of the calling code to anticipate or handle the problem. You cannot even rely on RAII to clean up on the way out.
If you permit the compiler to generate exceptions, but disallow code from outside the STL from using try
and catch
, then you still cannot rely on stack-unwinding and RAII to clean up when an error is thrown from within STL. The unwinding only happens up to the highest point the exception is caught.
And, lastly, the STL containers expect the contained objects to be copyable. If you live in exception denial, what do you do if you can't guarantee success from a copy constructor? You can't throw an exception, and there's no way to signal a failure.
The design of the STL assumes the caller isn't in exception denial.
new
does, and it's not really part of the STL. And you can get that cleanup if you change to int main( int, char** ) try { /*code*/ } catch( ... ) { throw; }
, otherwise being in denial. (Repeat for other threads.) - Potatoswatter
This is one misconception that prevents C++ from being used on Embedded Systems. The fact is that the equivalent exception handling in C amounts to the same time and space (perhaps a little more). The issue is that people don't write the equivalent exception handling in C; exception handling is generally ignored by C programmers.
Again, most people haven't implemented polymorphism in C. Also, programs can be written in C++ that don't use virtual functions or polymorphism.
An equivalent program written in C would use the same space or more. It may use more because some of the issues already in the C++ language would have to be added to the C language program.
This comes down to price, duration, and skill sets (at least). A language that is best suited for a project (due to language features) may not be the best fit for the shop, especially when few people have experience in that language. A small team of experts in FORTRAN can develop more correct and robust software than a large team of newbies using a popular language. C++ was designed to be a generic language: it covers a wide base of requirements for many projects.
People forget that compilers can add padding between members.
Another thing started by the MFC...
C++ still supports free standing functions. Often, free standing functions are a better solution than members in classes.
inline
keyword forces the compiler to inline code.register
keyword forces the compiler to use a register for variable.These are only suggestions to the compiler. The compiler can ignore your suggestions.
exceptions should only be used for exceptional situations.
- exceptions should only be used for exceptional situations.
- exceptions should only be used for exceptional situations.
- BlueRaja - Danny Pflughoeft
iostream is a lot slower than stdio.h
Reason why iostream performs poorly compared to stdio is because it synchronizes its buffers with stdio ones (in order to ensure that output to the screen from both libraries follows the order of calls in the code). A simple call solves the problem by disabling synchronization:
ios_base::sync_with_stdio(false)
That it's just "C-with-classes" or "Complicated-Java-without-garbage-collection".
Perhaps more of a DailyWTF than a myth, but here goes...
The lecturer at my alma mater who taught me C++ taught our class that in this example:
for (int loop = 0; loop < 10; loop++) {
// Do something with loop
}
... loop
would be incremented at the end of the block and in this one:
for (int loop = 0; loop < 10; ++loop) {
// Do something with loop
}
... loop
would be incremented at the beginning.
Of course, as soon as we started using for
-loops in the labs, most of us learned that this was nonsense.
However, five years after my graduation a young guy joined my team and during a code-review he explained that he was pre-incrementing his loop variable so that it was incremented at the beginning of the block. When I asked him if he was taught by [name withheld] it transpired that he was. I dread to think how many graduates left the same university with this misconception.
I dread to think how many graduates left the same university with this misconception
- if this was the worst misconception... no harm done (it will manifest at the first test run). Now, other myths ("Problem X is NP-hard", or "use rand()%10
to get a uniform distribution of integers [0,10)"... these are the things that cause real damage.) - sehe
Early C++ programs flushed down the toilet grew into alligators in the sewers
(or am I getting urban myths confused?)
Your comment about TR1 shows something of a misunderstanding. TR1 was never intended to be a change to the base standard. TR stands for Technical Report, which means it's a separate document about whatever is specified in the associated standard -- in this case, C++.
It's not a proposed change to the base document that failed. Rather, it's (essentially) a whole new standard associated with the original one. Although it's only really intended to be useful in conjunction with the C++ standard, otherwise it has essentially the same status as the C++ standard itself -- i.e. anybody who wishes to do so can provide a conforming implementation of it.
It's also worth pointing out that nearly all of TR1 has been accepted into the draft standard for C++ 0x. The only part that's been changed to any significant degree at all is the random number generators. As such, although TR1 itself isn't (and never will be) part of the C++ standard proper, essentially the same things under slightly different names (I.e., in namespace std:: instead of std::tr1) will be part of of standard C++ relatively soon.
From a practical viewpoint, I'm hard put to figure out why anybody would care either way though. For most people, the standard is important primarily to the degree that it allows portability. From that viewpoint, TR1 is much more "standard" than support for export
, for one obvious point.
Edit: As to whether TR1 and its contents will go away anytime soon, I consider it quite unlikely. The situation has been discussed [1] before. I'd give considerable weight to Peter Becker's answer -- as current C++ 0x editor, he's probably more aware of this issue than anybody else.
[1] http://groups.google.com/group/comp.std.c++/browse_frm/thread/ff5dacf64e5fc9c8/7cebb6c85031ab70Myth:
Everything is an object.
(I really wish it was sometimes)
Myth: C++ should be the first programming language a student learns.
C++ is not suited for use in embedded systems
Refer to http://stackoverflow.com/questions/2855884/use-the-right-tool-for-the-job-embedded-programming
Myth: C++ is high-level and lets you avoid C features.
The inclusion of most of the STL in the C++ standard library did add some much needed high-level data types. But they aren't integrated into the language itself: The core C++ language is still very C-like.
"abc"
is a const char[]
, not a std::string
. You can write int x[] = {1, 2, 3};
but not vector<int> x = {1, 2, 3};
(until C++0x becomes popular). this
and argv
are pointers.
The C++ standard library isn't consistent about using the modern style. fstream
takes a const char*
for the filename, not a std::string
.
Thus, you can't understand C++ without understanding C-style arrays and pointers.
C++ is basically C with classes.
C++ is much more than that! Is a multi-paradigm language and one that's capable of blending these paradigms harmoniously together to create code that would have been otherwise inferior had we used a single paradigm for the same problem. Skipping more subtle differences (ex: greater type safety, better variable scoping), let's consider just the multi-paradigm aspect.
Let's assume that we're writing a linked list and pretend that no linked list implementation, algorithms, or utilities of any sort to aid us already existed in the standard C++ library or boost.
We decide to use object-oriented techniques and generics and successfully create a list class capable of doing anything one would ever want to do to a linked list: insert elements to it, remove elements from it, and iterate through it.
Now we find that we want to be able to find elements in the list. What do we do?
Given primarily object-oriented techniques at our disposal (only classes), we might be tempted to:
In C++, a multi-paradigm language, the best solution is very obvious. Simply write a separate, free function for such auxiliary functions! When we do this, we get all the benefits of #5: no tight-coupling and therefore no vulnerabilities to list rewrites. The implementation could even change from a singly-linked list to a doubly-linked list or even a completely different sequence type, it doesn't matter as long as the public interface doesn't change. Unlike #3/#4 (composition approach), we don't have to duplicate the public interface of the list.
Finally, when we do things this way, we realize with additional paradigms like generic functional programming, that we can even generalize these separate list algorithms to work on a lot more than list types and even accommodate predicate-based searches without any abstraction cost.
Exception-handling is slower than error-handling (even for non-exceptional cases).
This may be the case on certain compiler implementations, but we need fair comparisons! How many times have we seen a real world system of any scale that properly checks for all possible errors (every possible malloc failure, just for one example) that the program can ever encounter and properly propagates them down the call stack manually to the error-handling site? Almost every function in the system would need to do some error handling to do this as thoroughly as exceptions, and we never find this kind of thoroughness in real world projects of any large scale. Of course any ideally-written code to thoroughly deal with all possible errors is going to be slower than code which ignores a lot of errors and doesn't thoroughly handle them.
Exception-handling is optional with C++ and can simply be turned off without side effects.
Consider what happens with std::list<T, Alloc>::push_back
when called to insert an object of type Foo
. We invoke the copy ctor of Foo
when we do this, and it could throw (ex: call to operator new threw std::bad_alloc
). Good implementations of the standard library will deal with this case very gracefully, rolling back everything done so far in the push_back
as though it were a transaction, yielding a valid list state as though we never inserted anything to the list. Turn off exception-handling and suddenly we have no way to get this kind of robust behavior. It's the same not just for the C++ standard library, but for all kinds of other C++ libraries that use, as an example, operator new (and not the nothrow version) like boost.
C++ hides code more than C.
Short of exception-handling and implicit constructors (which should generally be avoided), this is often not the case. This is a common argument made by people who lack experience using C++. Given a section of code, a novice might have a difficult time telling you where a destructor will be called given non-exceptional execution flow. An experienced C++ programmer would have no problem pointing this out.
C programmers are used to the idea that operators are not functions. C++ programmers are used to this and can easily point out where an operator will be invoking user-defined functionality. One only need look at whether the operands involved are PODs or not.
To the contrary, a lot of C systems hide code a lot more effectively from the programmer than C++. Consider the C preprocessor, for instance. Nothing hides code better than macros, as we cannot even practically trace through the code in a macro with a debugger.
Using directives should be avoided (ex: using namespace std;)
Sutter argues that using directives are what makes namespaces practical, and for good reasons. Without using directives, we have code that's very vulnerable to ADL-related problems. Virtually everyone agrees that argument-dependent lookup is very evil with the way it's inconsistently implemented across compilers, and using directives mitigate that problem far more effectively than, say, using declarations (ex: using std::cout
but forgetting to write using std::operator<<
or using std::list
but forgetting using std::swap
).
Inlining one-liners like accessor functions will make them faster.
Wrong and not even close. For all practical purposes, inlining such functions can reduce code bloat (provided the single line requires less instructions than pushing arguments to the stack, calling the function, popping, and returning), but even then inlining all instances of such code can slow things down as it can cause the compiler to try to equally optimize less commonly-executed code branches with ones that are commonly executed (the compiler can't read your mind about the desired runtime behavior of your code). Inlining should always be done only with the aid of a profiler where one can appropriately analyze the most commonly executed branches of code and selectively inline to help the compiler, even for one-liner functions.
Myth:
Java, C# and other higher level languages are valid alternatives to C++.
When they are, C++ was probably used for a wrong purpose to begin with. In reality, only languages like C, Ada, Forth are alternatives to C++.
Pointers are just memory addresses
int*
doesn't advance the pointer 1 byte, but sizeof(int). It's why incrementing a pointer past allocated memory is undefined. The memory address certainly exists. The pointer does not. And of course, an implementation could map pointers to something other than memory addresses if it so chose.And in a similar vein,
Pointers are just integers
Code written in C++ is inherently more efficient than similar code written in any other language.
int arr[10]; int* p = arr+11;
? There's nothing to prevent me from adding 11 to a memory address. But with pointers it's not allowed -- because pointers are not memory addresses. - jalf
arr+11
, because of 5.7/5. It is similar to this one, which also invokes undefined behavior: int a[2][1]; int *p = &a[0][0]; p+2;
. Contrast it to this one, which does not invoke undefined behavior (using the same array): p+1+1
. The first +1 will point to the second sub-array, to which you then add 1. If you do the addition in one go, you go straight out of bounds of the first sub-array. (note the binding is (p+1)+1
). - Johannes Schaub - litb
int a[10]; int * p = &a[5]; p+2;
as I read 5.7/4 int * p should behave like an array of one int in this case or it's behavior is undefined. And it's the simple part, for example I can't make my mind if the following is or is not defined int a[10]; int * p = a; p+2;
. Am I transferring the arrayness of a to p or not in this case ? Using pointers and arrays became quite intricated with this pointer are not addresses mindset (and the worst is that no compiler I know care the less of that bullshit). Is the ISO game to break existing code ? - kriss
C/C++ is faster than Java in all scenarios
C++ is faster than garbage collected languages.
This is a generalization that is widely held, and is both logically and empirically wrong. It can be faster, depending on a lot of factors, but isn't always. This is touted to justify pre-mature optimizations (such as picking C++).
Technically, this is an argument about manual memory management (or reference counting) vs. GC, not about C++, but the MYTH is perpetuated in context of C++.
Plus, C++ has general-purpose garbage collection libraries available for it :)
http://www.parashift.com/c++-faq-lite/freestore-mgmt.html#faq-16.26
Note you could expand this into "C++ is faster than higher-level languages," and all of my points can be expanded to match.
rightLeft = new Node(); leftLeaf = new Node();
), create a massive tree, and then delete both. You'll find that both languages perform similarly. Change the new Node()
to use boost::object_pool and you'll find that the C++ code now runs much much faster. The truth is that the Java JIT compiler automatically uses memory pooling, while C++ doesn't, so if you're doing manual memory management, you have to do it intelligently, but it is faster. - Brendan Long
1) That you know exactly what the C++ compiler is doing. Lets face it very few people do and, even though I've been writing assembler for nigh on 15 years and have a better understanding than most of what the compiler is doing under the hood, I'm STILL amazed at some of the choices a compiler makes (good and bad).
2) That a number with a ".[n]" is a float. I've had so many problems on platforms without doubles with this one. Its amazing how slow a software double to float conversion is. please remember the 'f' on the end!
3) The NIH syndrome. OK I accept this isn't juts down to C++ programmers but I've found it more with C++ programmers than anywhere else. Its fine to use someone else's code. Just make sure you use code that comes recommended or from a reputable source. Nowt worse than relying on buggy code :(
double
, it's very common for all arithmetic to be done in double or extended precision, and so there's no efficiency advantage to using float
. - dan04
C++ is no longer a modern language
Actually it is syntactically most powerful imperative language.
C++ memory management model is old and inconvenient
Java was so proud to have garbage collector. In larger projects it ended up with explicit calls of methods like .dispose()
(in SWT for example) and a lot of troubles with threads. In C++ you have a choice (do it manually, use memory pools, smart pointers, garbage collectors).
Arrays are evil, you should always use STL containers instead
I'm falling to pieces, when I see people using std::vector for plain arrays with known size and no other functionality than subscript access, often without forward space reservation, calling push_back(), push_back(), push_back()....
Inheritance brings some performance overhead
No it doesn't unless method is not virtual and it is not called in aid of base class.
The whole software has to be written in C++. (No, only the optimized parts need to be written in C++).
int __Foo_Bar_baz__i_s9__Foo_Bar_p_cp(struct __Foo_Bar, void*, char*);
(or whatever format it was compiled with; you get the idea) - David X
C++ is low-level and requires more time to code
Low-level coding in C++ is optional. One look at the Boost C++ Libraries [1] and you'll quickly see that C++ is capable of some very high-level constructs, without performance penalty. C++ is unique in that it "rides the fence" and provides the best of both worlds.
Many concerns with the language can be mitigated simply by taking advantage of a library or two. You can use garbage collection [2], if you like. Add SOCI [3] and you have safe database access with a syntax that cannot be beat in any other mainstream language.
Give a competent coder any project and they can build it just as quickly in C++ as anything else... given the proper libraries and expertise.
[1] http://www.boost.org/print 'Hello, world'
Ruby: print 'Hello, world'
Lua: print('Hello, world')
C++: #include<iostream> int main() { cout << "Hello, world"; return 0; }
QED. - Imagist
Who's your audience? If you want to convince higher-level developers (as in higher abstraction) to learn C++, you should not go straight to C++ intricacies. In a very subjective way, I'm sure C++ is a fantastic language in its possibilities of fine grain tuning, though, as a C# developer, I'm still reluctant to go C++. I'd be delighted to be convinced that the productivity/performance ratio of C++ is higher than C# or Java or (your favorite high level language) ratio. Anyway, good luck for your article.
mutable
. - Potatoswatter
C++ is a better C
While there is great features in C++ and C is nearly a subset of C++, the base design choices are very differents. C++ is a quite high level OO programming language, even if very compiler oriented (which explains why you miss features like metaclasses but have templates). On the other side, C was born as a kind of quite low level portable assembly language.
Today as a low-level programmer I miss a really low-level language that would be object-oriented and replace C, I use C++ for such purposes but I do not believe it's C++ (there is probably one such language around I don't know of, may be go, but I'm still unsure).
A point that is largely overlooked with C vs C++ is that a C compiler is quite easy to write, while a C++ one is much more complex. When you are working really low level (think of automated parallelizers for GPU, compilers to silicium or such things) you may want to write a compiler to experiment (first hand experience, some times ago while in PHd I did it to try some features of an experimental superscalar processor). C++ is much too complex a target for such needs. The usual target is C, too bad there is no available simple OO target and you have to either stick with procedural paradigm or simulate OO programming using C.
I remember the days when C++ was a preprocessor for C and mourn of what was lost making it a language.
(T*)
or static_cast<T*>
seems awful wrong to me. :S That literally takes 1 second to type, and you're giving up an entire language! - GMan
Const accessors are faster
It depends, but usually no
You should only delete
a pointer if it is not null.
Even in a destructor in which the only things being done are deleting pointers that are mebers, it is important to set each deleted pointer to null after deleting it.
memset is a good, efficient and valid way to iitialize classes and structs to an initial default zero state.
The order of initialization of members can be controlled by the order in an initializer list.
Interior classes are a nice way to keep related concepts together.
Varargs are still the best approach to output streams.
If you know C, you can easily pick up C++.
i++ is always as fast as ++i
delete 0
will crash the program (wrong)Mangled names make it impossible to link C++ code with non-C++ code.
Truth: "Mangled names" are an implementation detail, not part of the C++ language. If your implementation makes it difficult to link C++ and non-C++ code, blame your implementation, not the language.
extern "C"
would be a useful tidbit for anyone in this situation. I don't think any implementation doesn't perform name mangling; it's as good as required if you don't want restrictions on exporting overloads. That said, more OO languages interface with C++'s object model than any other. - Potatoswatter
Myth: Since C++ is a standard it's the same everywhere
Fact: What C++ is in your environment depend on which compiler vendor and standard library you use. What compiles and runs fine in one setup might not compile or behave differently if you change some of these.
TR1 is part of standard C++
TR1 is a part of C++0x and it hasn't accepted yet. New MSVS and GNU GCC has particaly this extension.
Also you can use Boost library.
It is faster to use iterators to access a vector than operator[]
It depends on implementation of Standart Library
The C++ Standard contains something called the STL
Stl appears in HP and it wasn't part of standart library. Then stl became part of Standart Library of C++. But standart library also has streams, CRT, algorithms.
I very often use this name when i mean using vectors, stacks, etc.
C++ programmers are more round-shouldered than other
Code using operator[]
on std::vector
instead of .at()
runs faster (the latter does bounds checking). The truth: most often the compiler optimizes away any unnecessary bounds checking, making .at() just as fast. Only if the compiler cannot determine whether the index is going to be in bounds, it will keep the check.
Of course you might not get that optimization if your compiler does not optimize well or you haven't enabled optimizations.
Myth: C++ (and C, for that matter) has macros.
Sure, these languages have things they call macros, but these things are really just text-substitutions, which can get pretty hairy and complicated.
I am currently learning Lisp, and what convinced me to do so was learning about Lisp macros: things that mold the language to what you need it to do. Of course, they can be hairy and complicated as well, but they can do a whole lot more than C/C++ "macros".
Theoretically, C++ templates help somewhat, but those are hairy and complicated things attempting to alter a hairy and complicated language. In comparison to Lisp, which is (from what I've been able to do so far) a simple, beautiful language, that has archaic, hairy and complicated ways to do things that can be done more easily in more modern languages.
In any case, Lisp has real macros, and C/C++ doesn't.
Pre-incrementing an iterator performs significantly better than post-incrementing an iterator on modern compilers.
for (int i = -1; i < n-1;) doit(++i);
, which is stupid anyway. You've successfully argued that badly-written, confusing loops can sometimes be less confusing using post-increment. That's fair enough, but it is not what was asked for, which is any kind of reason to favour post-increment as a rule of thumb. - Steve Jessop
i++
on its own as a statement or a loop increment expression. When questioned why they do this, people tend to say either "++i is harder to read", which to me strains belief in their competence, or else "++i is premature optimisation". That sounds to me as though they don't want to be seen to be prematurely optimising, and hence are prematurely pessimising instead, i.e. writing the code they believe to be slower. - Steve Jessop
for (int i = 0; i < N; i++)
over for (int i = 0; i < N; ++i)
; yes, Martin Beckett, I'm looking at you. edit: @Greg D's comment is a defense I can understand. ;) - just somebody
++i
is less readable than i++
. They are actually both non-intuitive, and have not even a counterpart in maths or other real lifes ... - phresnel
printf
is part of "the STL". The containers/algorithms/iterators/functional parts of the C++ standard library arguably are "formerly known as STL", since the changes are so slight, but they aren't "a library". - Steve Jessopusing namespace urban
but if you preface them withrural::
they should be fine. - corsiKa