Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Agreed; probably upwards of 90% of the uses of shared_ptr I've seen (and 70% or so with unique_ptr) are by people who clearly don't understand the C/C++ memory model and are trying to write Java in C++, and half the remainder are by people who've lost track of ownership and lifetimes and paper over it by randomly sprinkling smart pointers throughout the codebase until it sort of works.

I'm not against smart pointers where they make sense, it's just whenever I see them I start bracing myself for the horrors that seem to inevitably follow.



Yeah, it's also one of my big gripes about Java or any managed language. You never know if some jerk library grabbed a reference to your object when you passed it to a function and decides to leak it via holding a ref.

It's also why I really like that Rust decided to go RAII/single-ownership and add a ton of friction(via RefCell) to make sure that you really want shared ownership. It forces you to get your house in order up-front which I've found almost always leads to a better design overall.


RAII really is a brilliant design, it both (mostly) solves the problem of manual memory management and is easier (for my brain at least) to reason about than deterministic (shared_ptr, Obj-C/Swift) or nondeterministic (managed langs) garbage collection schemes. Once I grokked it I've never looked at managed langs the same way again.

In C++'s defense it's not like the language or the compilers encourage you to use shared_ptr, but it's also true (mainly for legacy C-interop cruft) it doesn't do enough to nudge you to write code in a proper RAII style, nor to enforce correctness WRT ownership.

I like that Rust forces you to explicitly opt out of RAII and/or single-owner semantics. (Those are the "defaults" in C++ too, but too easy to implicitly or accidentally opt out of). On the other hand you can write Java in any language, and from the little Rust I've read, newcomers from managed langs will often daisy-chain enough smart pointers in a row to put any 13-year-old who just downloaded Unreal Engine to shame.

The last time I took a serious look at Rust I thought it took things too far in the other direction; you weren't able to use two (nonoverlapping!) data members of the same struct in a function, and the suggested workaround was to wrap it in a smart pointer. Has that issue been fixed now?


> The last time I took a serious look at Rust I thought it took things too far in the other direction; you weren't able to use two (nonoverlapping!) data members of the same struct in a function, and the suggested workaround was to wrap it in a smart pointer. Has that issue been fixed now?

I think that's largely been addressed. Are you talking about doing something like this?

https://play.rust-lang.org/?gist=cf5835d28946df6c5093d57b7ca...


It's long enough ago I can't remember exactly what I was trying to do except that it was trivially correct, but yeah I think that was it. Anyway, I'm glad that's been solved; looks like I've got some new weekend plans! :)


Awesome :).

Something else to keep in mind that while it's nice to have the borrow-checker validate everything it's okay to step around it if you've got a case that's gnarly and you know is valid. I've had some C callback stuff where I run into that occasionally, I can't encode the lifetime semantics to the calling function so I have to side-step it.

In that case things like RefCell(which are separate from (A)Rc/Box) are a great "escape hatch".

Obviously you should try and keep it to a minimum but don't let it be a complete roadblock.


Closures still borrow whole structs from the captured scope when they could only borrow the fields they actually need:

https://play.rust-lang.org/?gist=26b2efa859589a8172cad982f0d...

This is especially frustrating when it's self that is being captured. There's an accepted RFC for fixing this but I'm not sure when it's going to be implemented.


You can work-around that by capturing the fields you need individually. It's a little awkward but does let you express what you're trying to do there:

https://play.rust-lang.org/?gist=2463ff559d7f96f916d246272b1...

Agreed that it's not the best default behavior though. Generally I tend to try to keep unrelated things in separate structs for this reason(with the nice side benefit of keeping concerns separate).


I agree the example looks "obviously" correct. But my paranoia worries that an aggressive optimiser might write to bytes next to the actual fields in ways that render the code incorrect.

While that worry sounds insane, it is exactly the kind of thing C compilers have retroactively defined as Undefined Behaviour. So kudos to Rust for having the compiler tell you up front where it reserves the right to do stupid stuff in future.




Consider applying for YC's Winter 2027 batch! Applications are open till November 2.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: