This is only one step in a complex "codecision" process.
The European Parliament get a say in this, but are not the final authority. Software patents are not yet EU law, and still have more stages of debate/voting to go through before they hit the lawbooks.
I think the final decision rests with the European Council of Ministers under the process in use (those Ministers not being directly elected, but being appointed by the national governments) but I'm sure someone will correct me on that if I've lost the plot.
He cited a MEP - MEPs are elected by European citizens, as far as I know.
Correct.
The European Commission isn't directly elected, but then, it's the executive, not the legislatory part of the European government.
Unfortunately, that's rather misleading. The European Commission are essentially appointed (though by elected governments, one hopes) whereas the European Parliament consists of directly elected MEPs. Unfortunately, we have here a rather bizarre system where the EC probably holds more real power than the EP. There are other players involved here as well, but when it comes down to it, hearing a commissioner state that some of the EP's amendments are "not acceptable to the Commission" is a fairly chilling warning that they're going to over-rule them.
Of course, given the frequently misunderstandings about what is and is not being proposed here, and the fact that idiots trying to be clever appear to be alienating the very elected representatives who needed to be convinced, this could all be for the best anyway.
Right now, I don't want flashy, XML-driven power apps. I'd settle for a word processor where I can produce my document with minimal fuss and good quality results. Apparently the vast majority of other word processor users agree with me, because I don't see any big uptake of ueber-powerful macro systems, manipulation tools based on super-flexible file formats, or any of the other much-promised stuff.
The simple truth is that usability is nowhere near the point where these facilities add value yet. Before you can develop powerful extra tools, you have to get the basics right:
a clean but powerful UI (no, this is not impossible)
good basic navigation and editing capabilities
good basic structure and formatting controls
good basic tools (spell check, word count and mail merge would probably do for a very large subset of WP users).
These are essential for a serious document preparation system, yet no currently popular WP, commercial or free, even comes close to doing them all well. The serious people universally use either DTP packages or typesetting systems, and there's a reason for that.
When we reach the stage where a word processor can do these things well, without the user ignoring stylesheets because they're too awkward, having to look up the help every time they do a mail merge or finding that limitations in the document structure support prevent you doing what you want to at all in a non-trival document, then we'll be getting to the stage where more powerful "workflow" tools might be of real benefit.
The second stage, of course, is developing the tools to create those workflow tools, and making them sufficiently usable themselves that people actually take advantage of the advanced capabilities. Right now, we have some awesome-sounding automation tools available, but who really uses them? Not many people, IME. Much of the problem is that the automation tools themselves are, like the applications within which they live, simply too much effort to bother with.
Give me a usable basic WP and usable tools to automate it (XML-based or otherwise) and I will move the document creation world. Until then, don't call us...
Sure, and sometimes they result in a 5x or 10x increase in the number of lines required to do something, for no measurable benefits whatsoever.
I guess it just depends on whether your conventions suck because they try to be too clever, or whether they're well thought out and designed from the programmer's perspective.
If you check the European Parliament site, you'll find there's a briefing dated 1 September 2003 that implies those amendments are still on track, acknowledging significant differences in opinion among MEPs and concern for the impact on SMEs. The information is still relevant, unless something dramatic has changed this month.
I agree that GC is often misunderstood, but this is a very good example of my basic point: to make Java behave well, you have to do various things manually. The killer for finalizers is that they're still not guaranteed to run. Even if you do add a call to close(), there's still no guarantee it will ever execute, so somebody still needs to run close(), or at least System.gc(), explicitly. And of course, as you say, finalizers may not run promptly even if they do run automatically, because the GC can't be telepathic. That would make them inappropriate for resource release, even if their execution were guaranteed.
With the deterministic destruction semantics of various other languages, this stuff is automatic, and my argument is simply that this is a safer way to design the language, and thus Java's claims of improved safety are... exaggerated.
I still think you're misunderstanding the significance of this.:-)
In well-written C++, almost all objects are automatic variables, or ultimately contained within objects that are automatic variables). It's also far more common to pass by value or pass a reference than it is to start throwing ownership around using pointers. You don't write:
SomeType *st = new SomeType();
all over the place as in something like Java. You just write:
SomeType st;
under most circumstances.
Typically, a data structure type will own any objects within it, and that data structure will be an automatic variable somewhere. When the data structure object goes, so does everything in it, cleaned up by the container type's destructor.
Yes, of course, it does happen that you have complex data structures relying heavily on indirections. Even then, you'd typically just have a data structure type manage a pool of objects within the structure, and have the objects within the structure linked via that pool. Again, when the data structure goes, it just empties its pool in its destructor.
Of course, the last idea is starting to become a simple garbage collector, but it's far less complicated than a full-blown GC, and rarely needed in practice.
In other words, the C++ approach is far more powerful than just handling trivial cases. It handles pretty much all cases, and when it doesn't, just a little thought when designing the complicated data structures allows the idea to generalise. (I write code in C++ that deals with very complicated graph structures in a performance-sensitive application for a living, BTW.)
The only time the C++ approach really needs significant help is if you don't care about ownership and just start passing references to any old object all over your code. Of course having everything garbage collected makes that easier. OTOH, that approach is systematic spaghetti anyway, and completely contrary to modular design, so I can't say that I've ever missed the ability to do it. In any reasonable design, almost every object is either directly owned by another object or function, or naturally belongs in a pool that can have a single manager.
These posts are getting long, but I'll try to respond to each point you made.
Regarding using void*, yes, some C interface APIs do use it, because C lacks templates. However, I maintain that it is rare to need it in C++ otherwise.
Regarding the RAII vs. finally point, yes, I realise plenty of C++ programmers make the mistake of equating finalizers with destructors. That's wrong for two reasons, of course: you don't know if the finalizer will ever be called, and even if it will be, you don't know when, so it's an inappropriate method for resource release.
Regarding casting, yes, of course you can (and probably should, in Java) write a type-safe wrapper around a generic container class. The point is that this is another requirement imposed on the programmer, whereas again in C++ it's handled by the language itself via templates.
My general problem is with the claim that Java is safer when the common idioms are manual (use finally, write a type-safe wrapper, etc.) whereas C++'s common idioms are more automatic (RAII, templated container classes). Automatic is always going to be less error-prone; that's the fundamental benefit of GC.
Now, to answer your specific questions, since I don't like ducking such things...
If you fail to close a FileInputStream explicitly and you're lucky, then the finalizer will kick in when the stream object is GC'd and close it for you. If you're unlucky, and the finalizer never runs, you have a resource leak. Alas, even Sun's own material sometimes implies that the finalizer will always clean up, which is not a safe thing to do.:-( At any rate, it's much better practice to call my_stream.close() explicitly in a finally block when you're done with the stream.
I mentioned the use of wrappers for generic container types, and my problem with the idea, above.
There is no class you inherit in C++ to guarantee resource release. Instead, for each resource type you typically have a manager class, which would attempt to acquire the resource in its constructor, hold the resource handle in some internal data member, and release the resource in its destructor. Examples of this idiom are the fstream, string and vector types from the standard library.
In each case, you just use these to access your resources, and never have to write the release code again. If the resource ownership is handled by whatever library supplies the resource -- and in decent libraries it invariably is -- then you never have to worry about the release issue at all, and you never have to write even a single line of release code yourself.
And yes, I've come across the books you mentioned. I think I first met Bloch's book when someone was discussed the type-safe enum idiom, for example. Didn't someone later write a lengthy criticism demonstrating that that idiom wasn't so safe after all, though? Of course, if you used C++ you'd have automatic enum handling and not have to do it manually anyway, but... (Yeah, yeah, I know that a language with proper disjunctive types kicks C++'s ass, I'm just messing now.)
Why? The whole point of deterministic destruction is that you can rely on destructors to clean things up, and in C++, the accepted idiom for resource management does just that. If the destruction is happening at the "wrong time", it's probably a symptom of a design flaw (see my other post in this subthread).
Sure, explicitly free your descriptors and whatnot -- that makes the code clearer -- but also do it in the destructor (wrapped in a suitable check so you don't do it twice, of course) as a back up.
Actually, I'd argue that most of the time, you shouldn't be releasing anything directly. If you find yourself writing my_file.close(), consider whether you've got the my_file object at the right scope in the first place.
What does it mean to refer to my_file after the close() call anyway? In most cases, the answer is "not a lot", in which case you'd do better to build your code so that my_file is only in scope when it's useful, and thus automatically closed by the destructor as soon as you've finished with it.
I'm afraid you just mentioned a few standard issue rants about C++ (all of which, as you can tell from the replies, are actually pretty groundless). The tone of your post wasn't clear -- I thought you were trolling initially as well -- so just put it down to bad luck, I guess.
I think perhaps you're still misunderstanding slightly.
The idea is that you wrap the resources in an automatic variable -- something that *will* be destroyed automatically when it goes out of scope. You cannot forget this, because the language does it for you. Now, have the destructor for that automatic variable release the resource it manages and bingo, you can never forget to release the resource.
The idiom is known as "resource acquisition is initialisation", BTW, if you want to look it up.
If your goal is to get promoted, out-perform your requirements.
Or make an effort, do a good job, and then move somewhere else on the back of a track record that says you get things done. This doesn't require 90 hours weeks and sucking up to your boss. In fact, it's well known that people who are well-treated by the employer, who don't work stupid numbers of hours, and who maintain a good work-life balance, are generally far more productive than those who submit to abuse.
Your contract only states what the job requires of you.
No, your contract also states what you require of the job. In fact, contracts must be two-way things; a one-way contract has no consideration and is unenforceable in most jurisdictions.
It is unprofessional for an employee to be late all the time. It is also unprofessional for managers to claim that coming in a minute late a handful of times is grounds for dismissal. What goes around...
I do an excessive amount of casting in C++, because many things return a void*.
Really? In my experience, almost nothing uses a void* in C++. It's used occasionally in system call APIs, but rarely elsewhere. Templates have rendered it pretty academic in most other contexts.
I'm assuming that what you're referring to is lack of templates in combination with the generic containers in java.util.
Did you ever think for a minute that you're actually using them wrong?
You keep implying that I don't understand Java, without giving any supporting reasoning. This isn't very constructive, not least because you're way off-target in guessing my Java experience. Why do you think that I think finalizers are supposed to be destructors? Why do you think I don't know how to do resource management properly in Java? Why do you think I don't understand what finally is for?
OK, getting back to the point, how do you propose to store a set of Apples and pull them out of the container without casting in (pre-generics) Java? What is it that I, my colleagues, pretty much every book on Java I've ever read and Sun's own Java web site are all missing?
In Java, you explicitly tell an object that you are done using it, and then null out the reference. That seems pretty straightforward to me.
What is so horrible about the finally block? It should make your code smaller, not larger.
Java's manual resource management is indeed straightforward. It is also error-prone and a waste of effort. C++ moved past this years ago with RAII. Similar idioms are evident in many other languages: a resource-controlling wrapper is a standard example in LISP. With these idioms, write your resource release code once, and then get it for free every time you use the resource, without writing any more code at all. In Java, you have to remember to write a finally block and get it right every time you use a resource. The alternatives are safer, and require less code to use, than finally blocks.
As for the magical techniques we're all missing -- don't you think some of us might have read those books you mentioned?
What are your views on the difficulty of writing correct code in C/C++ versus say Java or C#?
The question wasn't directed to me, but I hope you won't mind if I chime in here.
Modern C++ allows you to cut out whole classes of errors by following just a few simple rules. If you're interested, here are some starting points to consider.
You should almost never use a "raw" array. Arrays are a primitive, low-level tool. In higher level code, they are best replaced by container classes. The standard library provides several useful basic cases: vector, string, list and map are perhaps the most useful. These are all more powerful and safer than raw arrays.
You should almost never use a "raw" pointer. For many tasks where pointers were used in C, references are a cleaner and safer solution in C++. For simple dynamic memory allocation, "smart pointer" classes are both more powerful and safer: the standard library provides the somewhat limited auto_ptr, and several more are widely available. For complex data structures involving many indirections, smart pointers are a good starting point, and may be enough even in quite complicated cases. If not, you can build your own tools using the same ideas, and then use these in your higher level code.
Understand the "resource acquisition is initialisation" idiom, and use it religiously. It's mentioned in several of the better textbooks, and I'm sure a quick web search will find you an explanation. This idiom is the basic reason why containers and smart pointers are safer than the raw equivalents. Using it always will pretty much guarantee that you never leak a resource -- memory or otherwise -- from a C++ program again.
Visit Boost. There are many wonderful toys here, some fixing basic limitations the standard library forgot, some useful general purpose tools (such as various smart pointers, as mentioned above) and some just awesomely powerful extensions (full blown libraries for regular expressions, expression templates, and other goodies).
If you're interested in learning how to program C++ safely, cleanly and efficiently, I promise you that all of the above are worthwhile investments of your time. When you're done, you'll find it even more offensive that so many C++ programs have memory leaks, buffer over-run vulnerabilities and seg faults through following NULL pointers. Your programs won't, though.
template <int N> struct Counter {
static const int value = Counter<N+1>::value;
};
I guess you'll get integer wraparound in the compiler breaking that eventually, but if you had arbitrarily large N available, as Turing-based stuff pretty much implies, then it would recurse indefinitely, no?
The Java generics solves [the type safe container] problem in a true type safe way (not a macro expansion such as Templates).
Yes, Java needs generics to catch up with where the rest of us have been for years. And no, C++ templates aren't just a macro expansion -- please see my other post in this thread on why that's a fallacy. Not that it's relevant anyway, of course, since C++ templates are a type-safe solution to the problem too, and that was the goal.
RAII was a later add on to C++ and patched a serious hole in the language.
Um... No. Do you know what the RAII idiom is?
Any language that can't be reasonablly coded without the use of a profiler that checks for memory leaks. Any language that does array checking by giving you an run time error pointing to Georgia. Any language that makes you walk hunched over, with one hand behind your back, and your shoes on the wrong feet so your programs don't blow up. C++ requires a much deeper knowledge of the quirks of the language, of the storage scheme before you can get any program to compile. It is said that it takes maybe 18 months of programming before a C++ programmer is any good.
I could expose every sentence above for the myths that they are, but why bother? If you want to learn the basic C++ techniques to write programs without memory leaks and random pointer problems, just go buy a decent introductory textbook.
I've worked on very large C++ projects, and I claim with some confidence that I don't introduce either memory leaks or random pointer errors in my code. I do this by using sound C++ programming practices. And yes, I do use tools like Purify to make sure that I'm getting it right. And yes, I am.
To someone who bothers to do their homework, C++ is a safer language than Java in many ways. They usually come down to the same thing: substituting a powerful idiom that you have to write once for a "simple" solution that you have to remember every time you use it.
/me claps, loudly and for a long time.
This is only one step in a complex "codecision" process.
The European Parliament get a say in this, but are not the final authority. Software patents are not yet EU law, and still have more stages of debate/voting to go through before they hit the lawbooks.
I think the final decision rests with the European Council of Ministers under the process in use (those Ministers not being directly elected, but being appointed by the national governments) but I'm sure someone will correct me on that if I've lost the plot.
Correct.
Unfortunately, that's rather misleading. The European Commission are essentially appointed (though by elected governments, one hopes) whereas the European Parliament consists of directly elected MEPs. Unfortunately, we have here a rather bizarre system where the EC probably holds more real power than the EP. There are other players involved here as well, but when it comes down to it, hearing a commissioner state that some of the EP's amendments are "not acceptable to the Commission" is a fairly chilling warning that they're going to over-rule them.
Of course, given the frequently misunderstandings about what is and is not being proposed here, and the fact that idiots trying to be clever appear to be alienating the very elected representatives who needed to be convinced, this could all be for the best anyway.
The parent post is right on the money here.
Right now, I don't want flashy, XML-driven power apps. I'd settle for a word processor where I can produce my document with minimal fuss and good quality results. Apparently the vast majority of other word processor users agree with me, because I don't see any big uptake of ueber-powerful macro systems, manipulation tools based on super-flexible file formats, or any of the other much-promised stuff.
The simple truth is that usability is nowhere near the point where these facilities add value yet. Before you can develop powerful extra tools, you have to get the basics right:
These are essential for a serious document preparation system, yet no currently popular WP, commercial or free, even comes close to doing them all well. The serious people universally use either DTP packages or typesetting systems, and there's a reason for that.
When we reach the stage where a word processor can do these things well, without the user ignoring stylesheets because they're too awkward, having to look up the help every time they do a mail merge or finding that limitations in the document structure support prevent you doing what you want to at all in a non-trival document, then we'll be getting to the stage where more powerful "workflow" tools might be of real benefit.
The second stage, of course, is developing the tools to create those workflow tools, and making them sufficiently usable themselves that people actually take advantage of the advanced capabilities. Right now, we have some awesome-sounding automation tools available, but who really uses them? Not many people, IME. Much of the problem is that the automation tools themselves are, like the applications within which they live, simply too much effort to bother with.
Give me a usable basic WP and usable tools to automate it (XML-based or otherwise) and I will move the document creation world. Until then, don't call us...
It doesn't enforce them; they're conventions. However, try these.
/me resists urge to write witty comment on what language they're using to script their web site...
You're [pinky] $1mil evil, but I'm [pinky] $1bil evil.
I'd make them maintain the code the guy next to them wrote last class.
}:-)
How does it go? "Young men think old men to be fools, but old men know young men to be fools"? :-)
Sure, and sometimes they result in a 5x or 10x increase in the number of lines required to do something, for no measurable benefits whatsoever.
I guess it just depends on whether your conventions suck because they try to be too clever, or whether they're well thought out and designed from the programmer's perspective.
No, no, you've got it all wrong.
Java is the programming tool of choice for discriminating wanna-be hackers.
}:-)
If you check the European Parliament site, you'll find there's a briefing dated 1 September 2003 that implies those amendments are still on track, acknowledging significant differences in opinion among MEPs and concern for the impact on SMEs. The information is still relevant, unless something dramatic has changed this month.
I agree that GC is often misunderstood, but this is a very good example of my basic point: to make Java behave well, you have to do various things manually. The killer for finalizers is that they're still not guaranteed to run. Even if you do add a call to close(), there's still no guarantee it will ever execute, so somebody still needs to run close(), or at least System.gc(), explicitly. And of course, as you say, finalizers may not run promptly even if they do run automatically, because the GC can't be telepathic. That would make them inappropriate for resource release, even if their execution were guaranteed.
With the deterministic destruction semantics of various other languages, this stuff is automatic, and my argument is simply that this is a safer way to design the language, and thus Java's claims of improved safety are... exaggerated.
What you should have done was send them all printed out, in separate envelopes. }:-)
(For the benefit of the uninitiated, British MPs are legally required to reply to every letter sent to them by one of their constituents.)
I still think you're misunderstanding the significance of this. :-)
In well-written C++, almost all objects are automatic variables, or ultimately contained within objects that are automatic variables). It's also far more common to pass by value or pass a reference than it is to start throwing ownership around using pointers. You don't write:
SomeType *st = new SomeType();
all over the place as in something like Java. You just write:
SomeType st;
under most circumstances.
Typically, a data structure type will own any objects within it, and that data structure will be an automatic variable somewhere. When the data structure object goes, so does everything in it, cleaned up by the container type's destructor.
Yes, of course, it does happen that you have complex data structures relying heavily on indirections. Even then, you'd typically just have a data structure type manage a pool of objects within the structure, and have the objects within the structure linked via that pool. Again, when the data structure goes, it just empties its pool in its destructor.
Of course, the last idea is starting to become a simple garbage collector, but it's far less complicated than a full-blown GC, and rarely needed in practice.
In other words, the C++ approach is far more powerful than just handling trivial cases. It handles pretty much all cases, and when it doesn't, just a little thought when designing the complicated data structures allows the idea to generalise. (I write code in C++ that deals with very complicated graph structures in a performance-sensitive application for a living, BTW.)
The only time the C++ approach really needs significant help is if you don't care about ownership and just start passing references to any old object all over your code. Of course having everything garbage collected makes that easier. OTOH, that approach is systematic spaghetti anyway, and completely contrary to modular design, so I can't say that I've ever missed the ability to do it. In any reasonable design, almost every object is either directly owned by another object or function, or naturally belongs in a pool that can have a single manager.
These posts are getting long, but I'll try to respond to each point you made.
Regarding using void*, yes, some C interface APIs do use it, because C lacks templates. However, I maintain that it is rare to need it in C++ otherwise.
Regarding the RAII vs. finally point, yes, I realise plenty of C++ programmers make the mistake of equating finalizers with destructors. That's wrong for two reasons, of course: you don't know if the finalizer will ever be called, and even if it will be, you don't know when, so it's an inappropriate method for resource release.
Regarding casting, yes, of course you can (and probably should, in Java) write a type-safe wrapper around a generic container class. The point is that this is another requirement imposed on the programmer, whereas again in C++ it's handled by the language itself via templates.
My general problem is with the claim that Java is safer when the common idioms are manual (use finally, write a type-safe wrapper, etc.) whereas C++'s common idioms are more automatic (RAII, templated container classes). Automatic is always going to be less error-prone; that's the fundamental benefit of GC.
Now, to answer your specific questions, since I don't like ducking such things...
If you fail to close a FileInputStream explicitly and you're lucky, then the finalizer will kick in when the stream object is GC'd and close it for you. If you're unlucky, and the finalizer never runs, you have a resource leak. Alas, even Sun's own material sometimes implies that the finalizer will always clean up, which is not a safe thing to do. :-( At any rate, it's much better practice to call my_stream.close() explicitly in a finally block when you're done with the stream.
I mentioned the use of wrappers for generic container types, and my problem with the idea, above.
There is no class you inherit in C++ to guarantee resource release. Instead, for each resource type you typically have a manager class, which would attempt to acquire the resource in its constructor, hold the resource handle in some internal data member, and release the resource in its destructor. Examples of this idiom are the fstream, string and vector types from the standard library.
In each case, you just use these to access your resources, and never have to write the release code again. If the resource ownership is handled by whatever library supplies the resource -- and in decent libraries it invariably is -- then you never have to worry about the release issue at all, and you never have to write even a single line of release code yourself.
And yes, I've come across the books you mentioned. I think I first met Bloch's book when someone was discussed the type-safe enum idiom, for example. Didn't someone later write a lengthy criticism demonstrating that that idiom wasn't so safe after all, though? Of course, if you used C++ you'd have automatic enum handling and not have to do it manually anyway, but... (Yeah, yeah, I know that a language with proper disjunctive types kicks C++'s ass, I'm just messing now.)
There, I think that's everything... :-)
Why? The whole point of deterministic destruction is that you can rely on destructors to clean things up, and in C++, the accepted idiom for resource management does just that. If the destruction is happening at the "wrong time", it's probably a symptom of a design flaw (see my other post in this subthread).
Actually, I'd argue that most of the time, you shouldn't be releasing anything directly. If you find yourself writing my_file.close(), consider whether you've got the my_file object at the right scope in the first place.
What does it mean to refer to my_file after the close() call anyway? In most cases, the answer is "not a lot", in which case you'd do better to build your code so that my_file is only in scope when it's useful, and thus automatically closed by the destructor as soon as you've finished with it.
I'm afraid you just mentioned a few standard issue rants about C++ (all of which, as you can tell from the replies, are actually pretty groundless). The tone of your post wasn't clear -- I thought you were trolling initially as well -- so just put it down to bad luck, I guess.
I think perhaps you're still misunderstanding slightly.
The idea is that you wrap the resources in an automatic variable -- something that *will* be destroyed automatically when it goes out of scope. You cannot forget this, because the language does it for you. Now, have the destructor for that automatic variable release the resource it manages and bingo, you can never forget to release the resource.
The idiom is known as "resource acquisition is initialisation", BTW, if you want to look it up.
Or make an effort, do a good job, and then move somewhere else on the back of a track record that says you get things done. This doesn't require 90 hours weeks and sucking up to your boss. In fact, it's well known that people who are well-treated by the employer, who don't work stupid numbers of hours, and who maintain a good work-life balance, are generally far more productive than those who submit to abuse.
No, your contract also states what you require of the job. In fact, contracts must be two-way things; a one-way contract has no consideration and is unenforceable in most jurisdictions.
It is unprofessional for an employee to be late all the time. It is also unprofessional for managers to claim that coming in a minute late a handful of times is grounds for dismissal. What goes around...
Really? In my experience, almost nothing uses a void* in C++. It's used occasionally in system call APIs, but rarely elsewhere. Templates have rendered it pretty academic in most other contexts.
You keep implying that I don't understand Java, without giving any supporting reasoning. This isn't very constructive, not least because you're way off-target in guessing my Java experience. Why do you think that I think finalizers are supposed to be destructors? Why do you think I don't know how to do resource management properly in Java? Why do you think I don't understand what finally is for?
OK, getting back to the point, how do you propose to store a set of Apples and pull them out of the container without casting in (pre-generics) Java? What is it that I, my colleagues, pretty much every book on Java I've ever read and Sun's own Java web site are all missing?
Java's manual resource management is indeed straightforward. It is also error-prone and a waste of effort. C++ moved past this years ago with RAII. Similar idioms are evident in many other languages: a resource-controlling wrapper is a standard example in LISP. With these idioms, write your resource release code once, and then get it for free every time you use the resource, without writing any more code at all. In Java, you have to remember to write a finally block and get it right every time you use a resource. The alternatives are safer, and require less code to use, than finally blocks.
As for the magical techniques we're all missing -- don't you think some of us might have read those books you mentioned?
Isn't everything?
(/me ducks as the vi advocates arrive...)
The question wasn't directed to me, but I hope you won't mind if I chime in here.
Modern C++ allows you to cut out whole classes of errors by following just a few simple rules. If you're interested, here are some starting points to consider.
If you're interested in learning how to program C++ safely, cleanly and efficiently, I promise you that all of the above are worthwhile investments of your time. When you're done, you'll find it even more offensive that so many C++ programs have memory leaks, buffer over-run vulnerabilities and seg faults through following NULL pointers. Your programs won't, though.
Something like this ought to do it.
template <int N> struct Counter {
static const int value = Counter<N+1>::value;
};
I guess you'll get integer wraparound in the compiler breaking that eventually, but if you had arbitrarily large N available, as Turing-based stuff pretty much implies, then it would recurse indefinitely, no?
Yes, Java needs generics to catch up with where the rest of us have been for years. And no, C++ templates aren't just a macro expansion -- please see my other post in this thread on why that's a fallacy. Not that it's relevant anyway, of course, since C++ templates are a type-safe solution to the problem too, and that was the goal.
Um... No. Do you know what the RAII idiom is?
I could expose every sentence above for the myths that they are, but why bother? If you want to learn the basic C++ techniques to write programs without memory leaks and random pointer problems, just go buy a decent introductory textbook.
I've worked on very large C++ projects, and I claim with some confidence that I don't introduce either memory leaks or random pointer errors in my code. I do this by using sound C++ programming practices. And yes, I do use tools like Purify to make sure that I'm getting it right. And yes, I am.
To someone who bothers to do their homework, C++ is a safer language than Java in many ways. They usually come down to the same thing: substituting a powerful idiom that you have to write once for a "simple" solution that you have to remember every time you use it.