5 ms·
I rather prefer Java: void f(int n, int x) { Gadget p = new Gadget(n); // ... if (x < 100) throw new Exception("Weird!); // no leak
by harrytuttle 13y ago
I rather prefer Java:
void f(int n, int x) {
Gadget p = new Gadget(n);
// ...
if (x < 100) throw new Exception("Weird!); // no leak
if (x < 200) return;
// ...
}
Yes, good night's sleep tonight after writing that...
- fhd2 13y agoThe point of the example is that this is how NOT to do it in C++. There are two better options: void f(int n, int x) { Gadget p(n); // Stack allocated // ... if (x < 100) throw new Exception("Weird!); // no leak if (x < 200) return; // ... } Or, if it really has to be a pointer: void f(int n, int x) { std::unique_ptr<Gadget> p = new Gadget(n); // Smart pointer // ... if (x < 100) throw new Exception("Weird!); // no leak if (x < 200) return; // ... } Both will be automatically freed as soon as the scope is exited.
- harrytuttle 13y agoWhat I was hoping you'd say :) This is fine until I want to do this, at which point C++ becomes a memory management bastard: void f(int n, int x) { Gadget g = new Gadget(n); // ... if (x < 100) throw new GadgetException("Gadget broke", x); if (x < 200) return; // ... }
- kybernetyk 13y agoyou can always fake a defer: void f(int n, int x) { Gadget g = new Gadget(n); std::shared_ptr<void> defer(nullptr, [g](void *) { delete g; }); ... But honestly ... I'd just use a stack allocated object - or a smart pointer. In the last year I didn't write one delete. (I'm a full time C++ dev).
- skrebbel 13y agoGadget g = new Gadget(n); That code won't compile unless Gadget has an assignment operator that accepts a pointer, which is, well, not a very common scenario. Note: I'm not trying to be nitpicky. I really don't understand what you mean when you write that you "want to do this". Now, I don't know anything about you, but based off your comments in this thread I'm not sure you have a working knowledge of C++.
- fhd2 13y agoWell, what's easy in Java here is that you're effectively always working with shared objects. That's easy to use, but in my experience quite error prone, I can't count how many memory leaks I fixed in Java/JS code. YMMV. In C++, you have various ways of referencing and passing objects, so you need to be aware of the lifetime and ownership of objects. It's arguably harder, and unfortunately, the C heritage makes it a lot harder than it needs to be :(
- easytiger 13y agoisn't that illegal?
- detrino 13y agoThis code makes no sense. I think you do not understand C++ very well.
- tspiteri 13y agoThe point is not about C++ vs Java, it is rather about writing C++ like you would write Java, which leads to leaks.
- Sharlin 13y agoJava: void f(int n, int x) { Reader fr = new FileReader("foo.txt"); // ... if (x < 100) throw new Exception("Weird!); // resource leak if (x < 200) return; // resource leak // ... } A garbage collector that gives a false sense of security is much worse than no garbage collector at all.
- harrytuttle 13y agotry/finally in Java / using in C# are designed for that scenario.
- pyrtsa 13y agoBut you'll need to document it very visibly that "Thou shalt call resource.close() whatever happened." C++ makes it possible for the library writer to take care of freeing the resources automatically.
- moron4hire 13y agoA class implementing IDisposable is that documentation. You shouldn't need more documentation than the fact that IDisposable is there.
- jasomill 13y agoAn annoying fly in this ointment is cases where objects assume the responsibility for calling Dispose on caller-provided disposable objects. While it should always be okay to "double-dispose", this is only a guideline, and can't be enforced by the language, so, to maximize future compatibility with classes outside your control, you should probably defensively avoid calling Dispose on an object that will have already been disposed by other means.
- Sharlin 13y agoAnd try/finally assigns the cleanup responsibility to the caller, not the callee, which just adds boilerplate and mental burden. C++ does not need a finally block due to RAII. The using block (and "try-with-resource" in Java 7) is a poor man's RAII emulation. Anyway, what if you need to share non-memory resources? Suddenly you cannot depend on the garbage collector, you cannot use try/finally, you cannot use using or try-with-resource - you need to handle the situation just like in C++, except you're given fewer tools to do it - and a poorer understanding of the situation if you've learned that you don't need to do manual resource management due to the garbage collector.
- pyrtsa 13y agoNitpick: if (x < 100) throw new Exception("Weird!); // LEAK! You shouldn't use `new` either when throwing exceptions. Just: if (x < 100) throw Exception("Weird!); // no leak.
- Sharlin 13y agoThe grandparent's code is Java, not C++.
- abrahamsen 13y agoYes, Java is a far superior language than C++ for writing Java code.
- harrytuttle 13y agoMy point entirely :)
- sgoody 13y agoI'm a C# dev and I totally agree with this. I've done a limited amount of C++ many many years ago before I even knew what garbage collection was and I keep thinking of revisiting it, but honestly in my line of work ("Enterprise") I don't need the mental overhead of dealing with things such as pointers and memory allocation. Perhaps, my view is outdated, but I get the impression that everything in C/C++ is just a little thorny when compared to other slightly more high-level languages, such as namespaces, package management, list comprehensions, library compatibilities, type strictness etc. I would like to be wrong about that though... I wish I had a little more motivation to spend some real time with C++ (or perhaps even C).