Several reasons
Header files
Every single compilation unit requires hundreds or even thousands of headers to be (1) loaded and (2) compiled.
Every one of them typically has to be recompiled for every compilation unit,
because the preprocessor ensures that the result of compiling a header might vary between every compilation unit.
(A macro may be defined in one compilation unit which changes the content of the header).
This is probably the main reason, as it requires huge amounts of code to be compiled for every compilation unit,
and additionally, every header has to be compiled multiple times
(once for every compilation unit that includes it).
Linking
Once compiled, all the object files have to be linked together.
This is basically a monolithic process that can't very well be parallelized, and has to process your entire project.
Parsing
The syntax is extremely complicated to parse, depends heavily on context, and is very hard to disambiguate.
This takes a lot of time.
Templates
In C#, List<T>
is the only type that is compiled, no matter how many instantiations of List you have in your program.
In C++, vector<int>
is a completely separate type from vector<float>
, and each one will have to be compiled separately.
Add to this that templates make up a full Turing-complete "sub-language" that the compiler has to interpret,
and this can become ridiculously complicated.
Even relatively simple template metaprogramming code can define recursive templates that create dozens and dozens of template instantiations.
Templates may also result in extremely complex types, with ridiculously long names, adding a lot of extra work to the linker.
(It has to compare a lot of symbol names, and if these names can grow into many thousand characters, that can become fairly expensive).
And of course, they exacerbate the problems with header files, because templates generally have to be defined in headers,
which means far more code has to be parsed and compiled for every compilation unit.
In plain C code, a header typically only contains forward declarations, but very little actual code.
In C++, it is not uncommon for almost all the code to reside in header files.
Optimization
C++ allows for some very dramatic optimizations.
C# or Java don't allow classes to be completely eliminated (they have to be there for reflection purposes),
but even a simple C++ template metaprogram can easily generate dozens or hundreds of classes,
all of which are inlined and eliminated again in the optimization phase.
Moreover, a C++ program must be fully optimized by the compiler.
A C# program can rely on the JIT compiler to perform additional optimizations at load-time,
C++ doesn't get any such "second chances". What the compiler generates is as optimized as it's going to get.
Machine
C++ is compiled to machine code which may be somewhat more complicated than the bytecode Java or .NET use (especially in the case of x86).
(This is mentioned out of completeness only because it was mentioned in comments and such.
In practice, this step is unlikely to take more than a tiny fraction of the total compilation time).
Conclusion
Most of these factors are shared by C code, which actually compiles fairly efficiently.
The parsing step is a lot more complicated in C++, and can take up significantly more time, but the main offender is probably templates.
They're useful, and make C++ a far more powerful language, but they also take their toll in terms of compilation speed.
The C++ standard guarantees the following:
static_cast
ing a pointer to and from void*
preserves the address. That is, in the following, a
, b
and c
all point to the same address:
int* a = new int();
void* b = static_cast<void*>(a);
int* c = static_cast<int*>(b);
reinterpret_cast
only guarantees that if you cast a pointer to a different type, and then reinterpret_cast
it back to the original type, you get the original value. So in the following:
int* a = new int();
void* b = reinterpret_cast<void*>(a);
int* c = reinterpret_cast<int*>(b);
a
and c
contain the same value, but the value of b
is unspecified. (in practice it will typically contain the same address as a
and c
, but that's not specified in the standard, and it may not be true on machines with more complex memory systems.)
For casting to and from void*
, static_cast
should be preferred.
Best Solution
Breaking changes to C++/STL projects are outlined here.
vs2010 will also use a different build mechanism in the for of MSBuild.
Unfortunately, the revamped Intellisense in vs2010 won't extend to C++/CLI which some people aren't too happy about, however native code developer can look forward to a more responsive environment (hopefully).