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

RAII-based memory management without GC, and the concept of ownership vs. borrowing are very C++-inspired concepts. The borrow checker, which is the main innovation of Rust, is automated checking of things C++ programmers spend a lot of effort thinking about.

I think the influence of C++ is much more than just the syntax.



Isn't this more of an artifact of our memory architecture and the way we (de-)allocate memory? In that sense, the C++ flying-by-the-seat-of-your-pants approach and Rust's borrow checker solve the same problem, and I'm sure a lot of C++ insight has made it into the ideas behind the borrow checker, but I'm not sure that makes Rust in a way derivative of ideas extant in C++-land.

To me, the borrow checker just feels like an additional type layer I have to reason and think about. In that sense, my thinking when reasoning about lifetimes in Rust is a lot more along the same lines I do in Haskell than something I would be doing in C++ (which I refuse to code in, I'm not capable of writing secure C/++ code.)


I think the programs that fit neatly into Rust's borrow checking patterns are the same ones that fit neatly into C++(11)'s approach to managing object lifetimes (move/value semantics).

The question is what happens when programs don't fit those patterns. Inevitably in any large real world application, there are some objects with lifetimes that need to be managed carefully and don't match conveniently with some sort of scope in a program.

With C++, this is where one would use std::shared_ptr, or something else. In rust, there's Rc. But either way, you've now stepped into a territory where object lifetimes and bugs can be messy.


I do not find reference counting problematic in practice. In Rust you have to go out of your way to introduce interior mutability in refcounted values, which discourages problematic patterns.

I find that in most cases where ownership patterns don't fit the Rust model, you can abstract the problematic parts into some kind of collection type and hide them in its own crate --- or better still, find an existing crate that does what you need.

The only remotely common case that still doesn't get handled well, in my experience, is the self-referential struct pattern --- when a value needs to contain references to other parts of the same value.


> The only remotely common case that still doesn't get handled well, in my experience, is the self-referential struct pattern --- when a value needs to contain references to other parts of the same value.

There's a basic reason for that, namely you can't memcpy a self-referential structure while keeping desired semantics. Rust now has a Pin<> feature to mark data that should not be moved in memory, but its use is still unintuitive and IIRC requires unsafe. In many cases one should perhaps avoid references to self-addresses entirely; often they can be replaced by indexes and/or offsets.


> There's a basic reason for that, namely you can't memcpy a self-referential structure while keeping desired semantics.

You actually can! For instance, consider a struct with two fields: a Vec<T>, and a &T which references one of the elements of the Vec. Moving the struct (which does the memcpy) does not reallocate the Vec, so the reference in the &T would still be valid. But as far as I know there's no way to represent that in safe Rust; the &T in the struct requires a lifetime, and there's no way to represent "the lifetime of the other field" or even "the lifetime of the struct itself" (something like &'self T).

Yeah, you can use an index in my example (replacing the &T by an usize, and looking up on the Vec every time), but it's not a perfect replacement. A reference would always be valid (and always pointing to the same element), while an index can become invalid if the Vec is truncated, or point to a wrong element if an element is inserted or removed before it in the Vec.


Right, I know what the reason is, but that doesn't stop it from being a problem.


Maybe that has more to do with almost everything new have been garbage collected for the last decades (and that is such a tragedy) and less to do with C++.

It is a low-level programming language after all. Not being explicit about memory would be a bad thing (it almost always is).


I was under the impression that RAII specifically (as opposed to manually calling malloc and free by hand) was an innovation of C++, but I could be wrong.


Ada and Object Pascal also have it.


Don't know, but the concept is very useful and has found its way into many languages, such as thr using statement in C#.

It is just that it is typically more useful/powerful in languages that lack a GC (doesn't necessarily need to be that way though, but my impression).


C# using is Common Lisp's with-....


> RAII-based memory management without GC, and the concept of ownership vs. borrowing are very C++-inspired concepts.

Why are you crediting C++ for an idea that is probably much older than it?


Because it was C++ that made it mainstream.


I'd love to know where C++ got it from, but I can't find it. Any ideas?




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

Search: