On 3 Aug, 02:47, Roy Smith <r...@panix.com> wrote: > This one I don't understand. Yes, I get RAII, but surely there are > valid reasons to allocate memory outside of constructors. Containers > which resize themselves (such as std::vector) are one obvious example.
That is because an exception might skip an arbitrarily placed delete[] or std::fclose when it rewinds the stack, so to avoid resource leaks they must be places inside a destructor of an object on the stack (which will be called). This is unsafe, anyone who writes this in C++ should be flogged: void foobar() { std::FILE *fid = fopen("whatever"); // some code here std::fclose(fid); } This idiom is safer : struct File { std::FILE *fid; File(const char *name) { // acquire resource in constructor fid = std::fopen(name); if (!fid) throw some_exception; } ~File() { // free resource in destructor if(fid) std::flose(fid); } }; void foobar() { File file("whatever"); // some code here } It is for the very same reason we should use std::vector instead of new[] for arrays. It is why new and delete should only be used inside constructors/destructors. It also why C++ has references in addition to pointers. Which means this is bad in C++, as new and delete is arbitrarily placed: void foobar() { File *myfile = new File("whatever); // some code here delete myfile; } An object should go on the stack, because if an exception is thrown, we need the destructor call. Which is why this (as shown above) is ok: void foobar() { File file("whatever"); // some code here } This is the kind of gotchas that allows C++ to shoot your leg off. In comparison C is much more forgiving, because there is no exceptions (unless you use setjmp/longjmp). This is ok in C, but not in C++: void foobar() { FILE *fid = fopen("whatever"); // some code here fclose(fid); } For the same reason we can place malloc and free wherever we like in C code. But in C++ we must restrict std::malloc and std::free (as well as new and delete) to constructor and destructor pairs. This kind of design is mandatory to make safe C++ programs. But it is not enforced by the compiler. And since the majority of C++ programmers don't obey by these rules, Java and C# tends to produce far less runtime errors and memory/resource leaks. And C++ textbooks tends to avoid teaching these important details. I'm inclined to believe it is because the authors don't understand it themselves. Objects on the stack are also required for operator overloading in C+ +. A common novice mistake is this: std::vector<double> *myvec = new std::vector<double>(10); myvec[5] = 10.0; // why does the compiler complain????? And then the novice will spend hours contemplating why the stupid compiler claims the type of myvec[5] is std::vector<double>. There was recently a post to the Cython mailing list claiming there is a bug in Cython's auto-generated C++ because of this. But this is how it should be: std::vector<double> myvec(10); myvec[5] = 10.0; // ok And now we see why C++ has references, as that is how we can efficiently reference and object on the stack without getting the operator overloading problem above. C++ is good, but most programmers are better off with C. It has fewer gotchas. And if we need OOP, we have Python... Sturla -- http://mail.python.org/mailman/listinfo/python-list