The GC is the way to go for complex application. The reason is simple: the GC has a global overview over all memory usage of the application (minus special stuff like OpenGL textures). This means that the GC can reuse previously allocated memory blocks, defragment memory transparently, automatically detect and elimitate leaks etc.
Yes... all you say is true, but it's what you are not saying that is what disqualifies a GC'd language for being a successor for C or C++.
C and C++ are used for:
1. Kernels.
2. Video codecs.
3. Video games.
4. Embedded programming.
I program in C++... and Python, and Java, and Javascript, etc, and I'm well aware of the benefits of GC. I also undertand how GC is implemented and the kinds of amortized performance benefits you can get. I'm also aware of it's drawbacks. The reason you can't use a GC'd language for any of these platforms is twofold.
1. GC must periodically halt all threads to compact the heap. Imagine if your kernel did this. The *whole computer would halt*. If anything displayign realtime graphics did this, such as a video game, you would get stutter.
2. GC is lazy about deallocation, so it chews up more heap space. Usually at least twice as much as the equivalent non-gc program. This isn't that big of a deal in most cases. but it means you can't use it for embedded devices where you might only a killobyte or two of ram. Yes, there are many of these devices, you probably use several.
Look, GC is great from a usability perspective. I would always prefer to use GC. HOWEVER, there are cases where GC will *just not work*, and I wish GC zealots would get that through their heads. The GC hammer is nice, but *sometimes* a more complicated and powerful tool is necessary for a more difficult job.
D did another thing right: it did not remove destructors, like Java did. Instead, when there are zero references to an object, the GC calls the destructor *immediately*, but deallocates the memory previously occupied by that object whenever it wishes (or it reuses that memory). This way RAII is possible in D, which is very useful for things like scoped thread locks.
Yes, destructors in C++ are very nice.
I'm actually kind of confused about this. Are you saying that D keeps a reference count *in addition* to doing GC, or are you saying that the destructor is called when the object moves out of scope like in C++?
- no multiple inheritance (which does make sense when using generic programming and metaprogramming; just see policy-based design and the CRTP C++ technique for examples)
I could not agree with you more. I do not understand multiple-inheritance phobia. If you have a good grasp of how objects and classes work, then multiple inheritance is not only safe, but incredibly useful as a way of adding mixins to a class. This is doubly true in conjunction with meta-programming and templates.
Fear of multiple inheritance tends to stem from the diamond problem... but really if your class hierarchy is is 3 layers deep, that is your *real* problem, not multiple inheritance. You want to restrict the *depth* of the tree, not the *breadth*.