3 ms·
RAII is almost zero cost abstraction and the only reason it isn't is because C++ is made out of landmines (UB and complex, dated ABI, etc). If you can use refe
by CuriousCosmic 3y ago
RAII is almost zero cost abstraction and the only reason it isn't is because C++ is made out of landmines (UB and complex, dated ABI, etc).
If you can use references (and sometimes moves), you can produce code that zero cost abstracts for RAII but there are a bunch of arcane rules that you need to follow to guarantee this (and you'll need to double check the generated assembly to verify this).
Now if you need to interact with pointers, you'll need at minimum `unique_ptr` which is not zero cost. It's low cost but there are a bunch of reasons why it can almost never be truly equivalent to a regular pointer. You can get it there but you'll need to follow even more arcane rules and even then sometimes it'll just not be possible to get true zero cost unless you use a custom version of the stdlib and likely the compiler to force the build to disregard ABI safety/compat.
Compare this to Rust where UB is supposed to be non-existent outside `unsafe`, where the compiler far better understands when code is crossing a potential ABI boundary and what specific parts of that boundary need to be upheld, and just in general better understanding when two things can't actually interfere with each other vs when they can.
So rust isn't true zero cost abstraction either by any means but it is so much closer to zero cost than C++ and that's without the cognitive overhead that C++ brings with it.
- pipo234 3y ago> Landmines [..] arcane rules [..] So you're (primarily?) referring to "cognitive overhead" rather than more usual meaning of overhead as in "runtime overhead". Not sure about the ABI differences and how this ties into problems and limitations of `std::unique_ptr`. I find it usually straight forward to write "assembly level optimal" code and rarely if ever have used raw pointers in C++14, C++17. Can you given an example? Let me be clear, C++ is a great language but I fully concur that it takes great skill and resolve to consistently navigate about the landmines you allude to. Rust is much easier in that sense (though I don't agree UB is non-existent outside of `unsafe`). But in terms of runtime overhead, memory use and even source code size, Rust occasionally forces my hand considerably harder (e.g. `RC<RefCell<..>>` vs `std::shared_ptr<>`)) in the direction of performance compromise. Again, not a problem per se when balanced against easier to develop and maintain code but I would persist that C++'s RAII is closer to the metal than Rust's.
- TwentyPosts 3y agoWhen it comes to the overhead issues of unique_ptr, I always think of this video here: https://youtu.be/rHIkrotSwcc?t=1192 https://youtu.be/rHIkrotSwcc?t=1192 At 26:50 he gets into how this relates to ABI, and how 'fixing' some of this would require a pretty severe ABI change, as well as destructive move semantics, which would require a severe change to how C++ works. I frankly don't understand C++ well enough to fully judge about all of this, but everything he says seems entirely solid, and showcases how unique_ptr is in fact not zero-cost, and can in fact be a significant performance trade-off when you really need that extra bit of performance. > Rust occasionally forces my hand considerably harder (e.g. RC<RefCell<..>> vs std::shared_ptr<>)) in the direction of performance compromise. How so? Is RC<RefCell<T>> more expensive than std::shared_ptr<T>?
- deleted 3y ago[deleted]
- CuriousCosmic 3y ago> So you're (primarily?) referring to "cognitive overhead" rather than more usual meaning of overhead as in "runtime overhead" I'm referring to both. The issue is that all that complexity makes it very difficult for programmers to write code that the compiler is consistently able to optimise to (or close to) zero overhead. It can be done with enough work and care but for your average C++ developer, they aren't going to be seeing zero overhead for a lot of the things that C++ generally leads us to assume are zero overhead. > Can you given an example? To copy the link that TwentyPosts provided (which is coincidentally also the first thing that came to my mind, albeit at a different timestamp) https://youtu.be/rHIkrotSwcc?t=1054 https://youtu.be/rHIkrotSwcc?t=1054. The issues with `unique_ptr` in particular are that: - They force the compiler to generate exception code where maybe there isn't any necessary if you pass them into a function. You can elide this by going through and annotating things that you know can't except with noexcept however most people don't even care about noexcept in the first place and consider it line-noise. - Using move references to unique_ptr instead of pointers adds overhead by forcing the compiler to generate extra memory reads. - Passing by value should be zero cost but it'd require breaking basically every aspect of the C++ ABI to do so. Because of this you still get a double indirection which adds overhead. So your average C++ programmer probably won't do #1 which adds the largest overhead and if you need to transfer ownership you have to do #2 or #3. It's only really zero overhead when you can't transfer ownership (`unique_ptr<T> const &`) and even then, now you are looking over your shoulder and maybe it gives you overhead on rare occasions. > Let me be clear, C++ is a great language but I fully concur that it takes great skill and resolve to consistently navigate about the landmines you allude to. Agreed 100%. However I think to navigate some of those landmines you can't get rid of them, you just have to walk around them. > (though I don't agree UB is non-existent outside of `unsafe`) I agree that it's not non-existent however the UB outside `unsafe` is assumed to be a bug in the language that needs to either be fixed or formalised as defined behavior. > ... I think if you successfully navigate all of the landmines, C++ RAII can outperform Rust where Rust falls short and generally otherwise go toe-to-toe with Rust. However I think Rust gives you most if not all of that overhead reduction for a massively lower cost than C++ for the same benefit.