If you have a need for more than a few pthread_join(), fclose(), etc, something needs to be fixed. In my experience, RAII isn't a good idea. With RAII control flow is implicit and all over the place. With a little data structure organization work the C way is so much better. I'd much prefer 5 explicit fopen/fclose pairs in my program, and 5 lock/unlock, 5 malloc/free, etc., to having to code out-of-band and out-of-context ctor/dtor pairs for each type of "resource" (plus the paralysis when from having to decide what the resources are, what should happen automatically and what explicitly, etc).
Regarding the assembly example. If the copy matters performance-wise (note: it doesn't!) then DON'T MAKE A COPY. Have a pointer argument and put the result there.
> If the copy matters performance-wise (note: it doesn't!) then DON'T MAKE A COPY. Have a pointer argument and put the result there.
it sure does, especially if you're going to make a high performance graphics library. Some old benchmarks I found were on an average of 10-15% performance loss if calling non-RVO'ed code in some tight loop.
Is there a performance difference between C++ with RVO and C where the functions operate on pointers to structs instead of returning the struct directly? Or is it just a matter of coding style? This is something I could never understand very well.
That was tongue-in-cheek. Of course you can always find a slow instance for any approach.
The more explicit message is: You're optimizing the wrong thing. "Tight loop" and "RVO", these things don't go together. Don't write slow and complicated code and expect the compiler to magically make it fast. Write straightforward code. It's easy. It will be effortlessly fast.
There are very few cases where you need to work hard to get fast code (SIMD etc). Typically, if you need to work hard, the code will be slow.
RAII was created as a solution to the problem of C++ code not releasing its resources when an exception happened. By putting the resource release in a destructor this is fixed through piggybacking on C++'s semantic of calling destructors when objects go out of scope, even through exceptions.
To put it another way, RAII is a hack which co-opts one semantic to cover the drawbacks of another semantic. Without exceptions there's no need for RAII because there's no problem to solve.
RAII isn't only about exceptions (although it helps greatly); see Rust for example.
RAII is about any scope exit automatically cleaning up resources. Exceptions is a big one, but so is return, break, etc. Having it happen automatically in all cases is a win for robust software (in my opinion).
Regarding the assembly example. If the copy matters performance-wise (note: it doesn't!) then DON'T MAKE A COPY. Have a pointer argument and put the result there.