isn't it a lot neater?
Your C++ snippet misses the template implementation details which you include in you C example and neither have any "out of structs" handling so it's a bit hard to tell. However if we ignore the actual implementation and initialisation then it boils down to
MyStruct* s = takeOne();
....
releaseOne(s);
vs
ClipRectangle r = freeRectangles.removeFirst();
...
freeRectangles.prepend(r);
So it's probably pretty close in this case.
I have to say though that in many ways I'm not a big fan of C++ (even though I've written a lot of C and even more C++) because it's all too easy to a) write unmaintainable code and b) get screwed by language features.
Case in point - the code example you could easily not be doing what you think.
OK, it was a quick "illustrate the point" snippet and I'm not going to hold you to it actually working, or even compiling but picking it apart slightly the line
ClipRectangle freeRectanglesBuffer[5];
Suggests (only suggests mind you since we don't see the implementation) that the type of ClipRectangle is the class, not a pointer.
So
ClipRectangle r = freeRectangles.removeFirst();
could be a bit of a problem - it instantiates a new automatic ClipRectangle (calling its default constructor), then assigns it (calling op =) from the result of removeFirst() - rather a lot of copying will be going off (not great for efficiency) and more importantly you don't now have the one you thought you did - just an automatic variable holding a copy of the data.
Now
freeRectangles.prepend(r);
has the potential to bite you badly. For this to compile there would have to be a version of prepend() which took a ref - that's possibly not unreasonable depending on how you use the lists but you might just have stuck an automatic variable into a static list. Depending on the lifetime of the variables you might get away with this to some extent but you might not and the bugs produced are often difficult to track down.
Now the chances are that your template is pointer based and you meant to say
ClipRectangle *r = freeRectangles.removeFirst();
or even
ClipRectangle &r = freeRectangles.removeFirst();
There is a good chance that the compiler would have spotted the mismatch and thrown an error, especially in a fairly simple project which doesn't have loads of overloaded methods and multiple constructors but I've seen real code die on
exactly the above mistake in a project where the compiler was able to "helpfully" figure out a way to make the by value assignment work where a by pointer assignment was intended.
Don't get me wrong, I love C++ for
writing code. In fact I'd probably love it even more today than when I last seriously (i.e got paid for doing so) wrote a significant amount of C++ and several interesting features have been added to the language since then.
What I loath (and that's with a vengeance) C++ for is maintainability in all but the simplest of projects, especially when all the "nice" language features get used. It can be totally impossible to know what even the most innocuous of lines of code are actually going to do.