

Why RAII rocks - jjuhl
http://bromeon.ch/articles/raii.html

======
KeytarHero
Yes, of course RAII is much shorter than a contrived example designed to be as
long as possible. Here's a much shorter version:

    
    
        int unsafe2()
        {
            A* a = new A;
            int retval = 0;
        
            if (a->f())
            {
                B* b = new B;
        
                if (b->f())
                    retval = b->g();
                else
                    retval = a->g();
        
                delete b;
            }
        
            delete a;
            return retval;
        }
    

I agree that RAII is a good thing, but can we please avoid straw-man examples?

~~~
lumpypua
How does this version handle exceptions?

~~~
KeytarHero
It doesn't. Just like the example it replaces.

I'm not saying this is the best way to write this code - there are several
reasons RAII is better. But in this case, "look how messy non-RAII code is!"
isn't the reason.

~~~
st3fan
The original example does actually properly deal with exceptions.

------
zwieback
I was surprised how little I missed manual memory management when I switched
from C++ to C# for everyday work.

RAII is something I do miss, though, even after years of C# I still feel
lifetime management of objects is awkward.

~~~
tonyedgecombe
For unmanaged resources using provides almost the same thing, the only
downside I can see is it means yet more nesting.

~~~
MaulingMonkey
You can forget to write a using statement. In C++ you can omit your destructor
entirely if all the members are already RAII classes, whereas in C# you still
need to write a .Dispose() method.

Memory management is by and far the vast majority of resource management in
C++ for me, which C# takes care of with garbage collection - so I don't miss
RAII too much in C#. But if you tried to give me a C++ with using blocks but
no RAII (read: you gave me C) I'd scream.

RAII is no panacea[1] - I'd say C#'s manual resource burden without RAII is
still less than C++'s _with_ RAII. Which is why I don't miss it _too_ much.
But it'd still be a nice addition. And I missed it dearly during my initial
adoption of C#.

[1] e.g. in C++, you still have to worry about reference cycles, implementing
the RAII constructs in the first place if existing ones aren't suitable,
ensuring parents are kept in scope while referencing children, etc..

~~~
vodik
> But if you tried to give me a C++ with using blocks but no RAII (read: you
> gave me C)

If you don't care about MSVC, IMHO new C code should be using the gcc cleanup
extension:
[http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initial...](http://en.wikipedia.org/wiki/Resource_Acquisition_Is_Initialization#GCC_.22cleanup.22_extension_for_C)

~~~
MaulingMonkey
> If you don't care about MSVC

Even ignoring personal taste: I care about MSVC. I also care about clang. GCC
is the one compiler I'm able to not care about.

> IMHO new C code should be using the gcc cleanup extension

Even if I didn't care about MSVC, I'd disagree.

I'm OK with extensions that are "harmless" in that the program will still run
without them working if I #if them out on other compilers - error pragmas,
deprecation annotations, static analysis hints, pre-C++11 override keywords,
etc.

I'm not OK with self inflicting vendor lock-in for something as important as
cleanup rely on a specific compiler's extensions - especially not when we have
a perfectly standard, portable, significantly better tested (and thus less
likely to have bugs) reasonable alternative in the form of C++ destructors.

If I'm not using C++ destructors, it's either because:

1) I'm doing small changes to an existing C project (in which case I'd be
stylistically inconsistent with it's preferred cleanup patterns for minimal
gain, since it almost certainly doesn't use the gcc cleanup extension)

or

2) because I can't rely on having decent C++ compilers on my target platforms
(which means I can't rely on having GCC either, and thus can't rely on the gcc
cleanup extension by definition.)

~~~
vodik
For what its worth, it is only MSVC without support. gcc compiler extensions
are otherwise still rather portable. To clang and icc at least.

~~~
MaulingMonkey
> For what its worth, it is only MSVC without support.

How recently? I've been enough versions back that clang documented pragmas
haven't been available. The cleanup attribute... I can only find docs for GCC.
Although I see LLVM bugs for it, so you're right about clang supporting it -
at least on HEAD.

> gcc compiler extensions are otherwise still rather portable.

Portable or not, I'd say only about half the extensions I've sought out on
clang have actually been available. If that.

> To clang and icc at least.

I should note in scenario #2 above I don't have these available either, since
these are decent C++ compilers.

------
santaclaus
Love me some RAII. Also, why is C++ chock full of such opaque acronyms? RAII
and SFINAE come to mind.

~~~
wololongong
More: NRVO, Pimpl, SBRM, EBO, NVI, ODR, CRTP, STL, RTTI, TMP.

I've been using C++ for the past year at work. It's an absolute nightmare to
learn.

~~~
stinos
SBRM, EBO, NVI, ODR, TMP -> care to explain those?

Anyway it does prove your point: have been using c++ _way_ longer than you and
these don't immediately ring a bell. Always more to learn! (or at least,
always more super subtle details you'll only encounter once in a lifetime)

~~~
electricCoder
SBRM = Scope Bound Resource Management ( another name for RAII ) EBO = Empty
Base Optimization NVI = Non-Virtual Interface ODR = One Definition Rule TMP =
Template Meta Programming

~~~
stinos
Funny. I do know all those principles but had no idea there were common
abbreviations.

------
okasaki
Why would you heap allocate something that you're deleting in the same
function? Isn't there some equivalent length example that isn't so contrived?

~~~
EpicEng
There are numerous cases when one would do exactly that, which all boil down
to "this thing is too big for stack allocation." Ever done any image
processing?

~~~
mkale
In addition, RAII is useful for more than just memory [de]allocation: database
connections, resource handles, anything that you have to get/create and then
cleanup/release.

~~~
czinck
As someone that works 90% with python and 10% with C++, that's something that
gets missed in the debates about GC/manual memory management. It's a lot
easier to leak resources in python programs because the whole point is you
aren't sure what the lifetime is of some objects; if you knew, you wouldn't
need a GC. So I end up putting a with block pretty high in the call stack
holding the DB handles (most of the time) which is just a weaker form of RAII,
as you can't "allocate" anything further down the call stack.

I prefer working in python to C++, I just wish I had a lot more control over
things like this. And no, __del__ isn't a good solution as that opens a whole
can of worms (for one, it's not guaranteed to ever be called).

~~~
tstack
Python has context managers, which were added for exactly this purpose.

    
    
      with alloc_resource() as resource:
          resource.use()

~~~
czinck
I mentioned those. They work, but they're just a weak form of RAII without any
extra power.

~~~
tstack
Can you elaborate on "extra power"? A c++ constructor/destructor pair is
equivalent to __enter__ and __exit__. I fail to see how this grants a
significant amount of power. There's certainly differences, but the gap is
probably not as large as your weasel words make it out to be.

You complain about having to put initialization into 2 constructors, but
there's the flip-side with things like mutexes. In c++, you have to have 2
classes, one for the lock and one for the guard. Whereas with a context-
manager, you have one class and the locking code is in the __enter__ and
__exit__.

    
    
        with self.lock:
            self.do_stuff()
    

In that case, I would say that the context-manager is nicer.

~~~
czinck
I didn't have any example of extra power, just in with blocks you have some
downsides compared to RAII but no upsides. By downsides I mean that in C++ you
write the constructor/destructor and never worry about it again, but in python
every caller has to use a with block, plus what I said above about exceptions
being thrown before __enter__.

I haven't done much with mutexes, but doesn't having it split over 2 classes
introduce a race condition? Seems like a weird way to implement it to me.

------
kuon
Isn't that similar to ARC in Objective-C?

~~~
mcphage
ARC is (almost) purely automatic. You write your code however, and then a code
analyzer goes through it to figure out where to put the memory management
calls. (Also I'm pretty sure ARC still just does reference counting).

~~~
Joky
ARC stands for Automatic Reference Counting:
[http://en.wikipedia.org/wiki/Automatic_Reference_Counting](http://en.wikipedia.org/wiki/Automatic_Reference_Counting)

------
st3fan
Welcome to 2015.

------
dicroce
Does your language have mutexes and exceptions? You NEED RAII...

------
alexnewman
Rust is the answer. C++ is just soo legacy.

~~~
jjuhl
So what? Sure, rust is the new thing, node.js is the new thing, forget about
SQL since NoSQL is the current thing. Etc etc, Bla bla bla. I hate this "let's
chase every new thing and everything old is shit" attitude. C++ may be old but
it does a great job at what it is targeted for (just like Fortran and many
other "old" things). I'd really wish more people would stop chasing "new
shiney" and just get work done. C++ may be complicated and old, but it gets
work done.

Old, complicated and legacy does not equal bad.

~~~
nightski
It's also caused billions of dollars in damage. Hell, even just null pointers.
Saying it does a great job is very generous. Even if it is the best language
for low level work, it is still barely acceptable.

We should strive for advancement and progress in our field. There is a large
difference between this and chasing the latest fad JS framework.

Unless you are saying that programming is a solved problem and C++ is about as
advanced as we'll ever get.

~~~
falcolas
And Rust is still going through its shakedown cruise. I wouldn't yet be
comfortable taking it in the deep waters where C++ currently roams.

There's still a lot of need for tooling, testing, and letting people with
smaller projects (and/or non-Mozilla use cases) shake out the bugs.

Give it a few successful years post 1.0, and Rust will be in a better place to
truly take the mantle from C++.

~~~
oldmanjay
It's sort of funny that you're holding rust to a far higher standard than c++
has ever met. A more honest post would say "c++ will continue to be used
because c++ is what is used and that's how we like it."

~~~
falcolas
The only standard that I'm holding C++ to is that it's been around longer,
which means that the big holes have been patched (or bilge pumps dispatched),
and developers who use it are realistic about what they are able to achieve.

That doesn't seem like a very high standard to hold Rust to. The problem is
there's still holes we don't know about, and the developers who evangelize it
are all starry-eyed about "never having to deal with memory again!"

When the shine wears off a bit (on both the language and its users), the big
holes can be found and patched, the bilge pumps dispatched for the small ones,
and Rust can move forward with a lot more confidence.

