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... 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...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.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;
// ...
} 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). Gadget 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++.
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 :(
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.C++ makes it possible for the library writer to take care of freeing the resources automatically.
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.
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).
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.