Firstly, destruction upon leaving scope in Objective-C would add some magic unexpected behavior that doesn't conform to what we expect from standard C stack-based functions.
In C++, when an object is normally declared, it exists on the stack, therefore it will disappear when the scope ends. The fact that the destructor is called is nice.
In Objective-C, all objects exist solely on the heap. All object-orientation is done at runtime, not at compile time, which leaves it open to be a lot more dynamic and open to fiddling at run time than C++ is. This of course loses a lot of the speed that C++ has, but it's not a big deal in most standard applications.
Since creating an object requires specifically allocating it on the heap, having it destruct when the pointer leaves scope is no good. That kind of magic behavior is exactly what would lead to awful bugs in Obj-C. If you want short-lived objects, you call their autoreleased constructors, which means they will self-destruct next time the thread's event loop ticks. It's an extremely common pattern, and happens so often in code that you don't, as you claim, 'have to understand the details of the implementation'.
And there's absolutely no need for the derision in your post. Please make your points and defend them like a civilized person.
It is actually possible for compilers to help out with this in many cases: http://en.wikipedia.org/wiki/Escape_analysis
#include <cstdio>
#include <functional>
using std::printf;
using std::function;
function<int ()> f(int x)
{
function<int ()> g = [x]()
{
return 2 * x;
};
return g;
}
int main()
{
auto f1 = f(5);
auto f2 = f(6);
printf("f1() = %d, f2() = %d\n", f1(), f2());
return 0;
}
(Which prints `f1() = 10, f2() = 12`)Or did you mean nested functions in the sense of being able to form named closures so that they can call themselves with a headache? It is admittedly more or a pain to do that (if you want to return a closure), but it is still doable, using new and delete:
#include <cstdio>
#include <functional>
using std::printf;
using std::function;
function<int (int)>* f(int x)
{
function<int (int)>* g = new function<int (int)>();
*g = [g, x](int n)
{
if(n <= 0)
return 1;
else
return x + n * (*g)(n-1);
};
return g;
}
int main()
{
auto f1 = f(0);
auto f2 = f(1);
printf("f1() = %d, f2() = %d\n", (*f1)(5), (*f2)(5));
delete f1;
delete f2;
return 0;
}
Or did you mean something else?Edit: Or, you could do something Y-combinator-ish like this: http://rosettacode.org/wiki/Y_combinator#C.2B.2B but yeah, it is a bit of a hassle compared to named nested functions.
You don't know what `unwind-protect` is now do you?
The key thing is that it acts like a wrapper around a try/catch/finally-like block (including other forms of flow control), while allowing you to put arbitrary code in the execute and cleanup portions. You would get the same effect with RAII, most of it would be taken care of for you with the right RAII classes, and if you needed custom code then just write a custom RAII like class or be smart about handling it.
Although the C++ version wouldn't handle C's longjmp and also goto's. But if you use them you're not exactly coding in C++ then.
As much as I'm a fan of RAII in C++, it really is a "pure C++" idiom. If a C++ class is needed in Objective-C code that can @throw an NSException, then the C++ cleanup code really has to be invocable explicitly (because the destructor might not be called). For example:
MyCPlusPlusObject object;
@try
{
...
}
@finally
{
object.cleanup();
}I don't agree with this statement, at least for finally v RAII: RAII is far superior a tool to deal with scope and resource management, as it requires less work on the part of the resource user and is as a consequence far more secure. It also ties in with C++'s memory semantics and therefore exists "for free", which is nice. Even more so in as messy a language as C++.
RAII has issues, one being composition (a subject on which `finally` is worse, not better) and the second one being "in-place" operations, which `finally` can handle but — at the end of the day — should probably be implemented separately.
`unwind-protect` handles both case very nicely and is therefore — as far as I'm concerned — superior. Although it has an (easily dismissed) "inconvenient" over RAII of adding a special form to the language.
Smalltalk's `BlockClosure#ensure` is also quite nice in that department, though I'd say slightly inferior to `unwind-protect` as building on it is more expensive.